I am new to VB Script, but since it is straight forward, so I grabbed two fragments of code from the web and combine them into one in order to do my task.
Basically what I want is to run an application called "MapForce.exe" and produce an output file, then create a new directory and copy this file to this new directory too.
The code is straightforward:
'This is the line to call MapForce.exe and produce output file.
createObject("wscript.shell").exec "C:\Program Files\Altova\MapForce2011\MapForce.exe 834toASCII.mfd /BUILTIN /LOG ACS.log"
'These are the lines to copy that output file to the new folder:
sourceDir = "C:\Documents and Settings\Robert\test\result.txt"
destinationDir = "C:\Documents and Settings\Robert\test\"
const OverwriteExisting = True
strDirectory = destinationDir & replace(Month(date),"/","_") & " TOU"
Set fso = CreateObject("Scripting.FileSystemObject")
if not fso.FolderExists(strDirectory) then
Set objFolder = fso.CreateFolder(strDirectory)
end if
fso.CopyFile sourceDir & "*.*", strDirectory & "\", OverwriteExisting
Now it works: Mapforce.exe gets run, output generated, new folder created and a file copied to the new folder. But the question is, since the MapForce will take a longer time to finish and produce the newest output file, so line 1 takes longer time to finish, however, the remaining lines of doing copying task don't wait for it to finish, so the file gets copied in the new folder is always the old one, not the newest one generated by the application.
To put it in another way, the remaining lines hurry to finish the task without caring whether the first line (which runs the MapForce application) finishes or not.
So I wonder if experts could give me advice on how to force the remaining lines to wait for the first line gets finished and newest output gets generated?
You could use the WshShell.Run method.
The first parameter (REQUIRED) is the executable (including parameters).
The second parameter (OPTIONAL) specifies the window style.
The third parameter (OPTIONAL) specifies whether the scripts waits for the command to complete before continuing.
A sample:
Dim oShell
Set oShell = WScript.CreateObject("WScript.Shell")
returnCode = oShell.Run("Your.exe Param1 Param2", 1, True)
Related
Is it possible to run a single macro for all xls/xlsx files and if so how. The macro shown below scales the excel file to fit to single page which is necessary as the number of columns is 19 and is needed to convert it to pdf using lo cli.
Libre office version: 6.0.6
Macro has been recorded with libreoffice and can be seen below:
REM ***** BASIC *****
sub Main
rem ----------------------------------------------------------------------
rem define variables
dim document as object
dim dispatcher as object
rem ----------------------------------------------------------------------
vrem get access to the document
document = ThisComponent.CurrentController.Frame
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")
rem ----------------------------------------------------------------------
dispatcher.executeDispatch(document, ".uno:PageFormatDialog", "", 0, Array())
end sub
Please let me know if any info is needed regarding the tests.
Got the answer from one of the developers at Libreoffice and it works like a charm, so sharing it here. The link to the answer can be found here
Mike's Solution
First: your recorded macro wouldn't work: it doesn't apply changes, it just opens a dialog. Please always test recorded macros :-)
You may use this macro instead:
Sub FitToPage
Dim document As Object, pageStyles As Object
document = ThisComponent
pageStyles = document.StyleFamilies.getByName("PageStyles")
For i = 0 To document.Sheets.Count - 1
Dim sheet As Object, style As Object
sheet = document.Sheets(i)
style = pageStyles.getByName(sheet.PageStyle)
style.ScaleToPagesX = 1
Next
On Error Resume Next
document.storeSelf(Array())
document.close(true)
End Sub
It operates on the current document, and after setting the scale, it saves (overwrites!) and closes the document.
To use this macro from a command line, you need to save it to some of libraries, e.g. Standard. In my example below, I use Module1 to store it.
You may use this macro on a single document like this:
'path/to/LibreOffice/program/soffice' path/to/excelfile.ext macro:///Standard.Module1.FitToPage
To use it on multiple documents, you need to make this in a loop (mentioning multiple filenames as arguments to a single soffice invocation, like with shell globbing on Linux using *, will not work - actually, it will only run the macro for the last document, keeping the others open and unmodified). A loop for Windows could be like this:
for %f in (*.xls) do start /wait "" "C:\Program Files\LibreOffice\program\soffice.exe" "%f" macro:///Standard.Module1.FitToPage
I am running a matlab-script that produces a figure. To save this figure I use:
print(h_f,'-dpng','-r600','filename.png')
What this means is that if I don't change filename for each time I run the script, the figure filename.png will be overwritten.
Is there a way to save a figure to a default name, e.g. untitled.png, and then when the script is run twice it will make a new figure untitled(1).png instead of overwriting the original one?
You could create a new filename based on the number of existing files
defaultName = 'untitled';
fileName = sprintf('%s_%d.png', defaultName, ...
length(dir([defaultName '_*.png'])));
print(h_f,'-dpng','-r600', fileName)
Add a folder path to your dir search path if the files aren't located in your current working directory.
This will create a 0-index file name list
untitled_0.png
untitled_1.png
untitled_2.png
untitled_3.png
...
You could also use tempname to generate a long random name for each iteration. Unique for most cases, see section Limitations.
print(h_f,'-dpng','-r600', [tempname(pwd) '.png'])
The input argument (pwd in the example) is needed if you do not want to save the files in your TEMPDIR
You can try something like this:
for jj=1:N
name_image=sscanf('filename','%s') ;
ext=sscanf('.png','%s') ;
%%do your stuff
filename=strcat(name_image,num2str(jj),ext);
print(h_f,'-dpng','-r600',filename)
end
If you want to execute your script multiple time (because you don't want to use a "for") just declare a variable (for example jjthat will be incremented at the end of the script:
jj=jj+1;
Be careful to don't delete this variable and, when you start again your script, you will use the next value of jj to compose the name of the new image.
This is just an idea
I have to run a VB script which has 2 arguments. So I am running a command below.
Delete_Dummy1.vb
s C:\Users\c6342\Desktop\XML_to_CSV\Temp_Files\xml.csv C:\Users\c6342\Deskto
p\XML_to_CSV\Temp_Files\xml1.txt
**VB Script Sample - not working:**
**sourceloc** = WScript.Arguments.Item(0)
**destloc** = WScript.Arguments.Item(1)
Dim objFSO, dataArray, clippedArray()
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set oTextStream = objFSO.OpenTextFile("**sourceloc**")
Set newFile = objFSO.CreateTextFile("**destloc**")
It throws the error as file not found. But if I hard code the sourceloc and destloc and remove the arguments it is working fine. it is throwing error only when i am using arguments.
**Working VB Script sample:**
Set oTextStream = objFSO.OpenTextFile("C:\Users\c6342\Desktop\XML_to_CSV\Temp_Files\xml.csv")
Set newFile = objFSO.CreateTextFile("C:\Users\c6342\Desktop\XML_to_CSV\Temp_Files\xml1.txt")
This works fine. But as per my project requirement, I cant hard code these file locations. I can pass as parameters from command.
After a length discussion in the comments think it will be best to just update my answer.
The reason for the Arguments not working is you never pass them to the OpenTextFile() and CreateTextFile() methods. Instead you are passing literal strings containing the variable name instead of the actual variables.
sourceloc = WScript.Arguments.Item(0)
destloc = WScript.Arguments.Item(1)
Dim objFSO, dataArray, clippedArray()
Set objFSO = CreateObject("Scripting.FileSystemObject")
'Pass the variables not a string literal
Set oTextStream = objFSO.OpenTextFile(sourceloc)
Set newFile = objFSO.CreateTextFile(destloc)
As it stands VBScript keeps trying to locate a file called sourceloc and destloc instead of the actual file names from the passed Arguments collection. Which is what likely causes the
Microsoft VBScript Runtime Error: File Not Found
Note: Below is based on initial question which has since been revised.
This comes down to how you are passing the arguments to the script, any spaces in the values will be treated as new arguments. At the moment this is how the arguments are passed;
0. C:\Users\enter
1. code
2. herec6342\Desktop\XML_to_CSV\Temp_Files\xml.csv
3. C:\Users\c6342\Desktop\XML_to_CSV\Temp_Files\xml1.txt
I'm sure this isn't what you expect. To avoid this enclose each argument in double quotes ("...").
Delete_Dummy1.vbs "C:\Users\enter code herec6342\Desktop\XML_to_CSV\Temp_Files\xml.csv" "C:\Users\c6342\Desktop\XML_to_CSV\Temp_Files\xml1.txt"
That way you get more what you expected
0. C:\Users\enter code herec6342\Desktop\XML_to_CSV\Temp_Files\xml.csv
1. C:\Users\c6342\Desktop\XML_to_CSV\Temp_Files\xml1.txt
Im trying to create a batch script to call a .exe to carry out analysis on multiple data files in a same folder. The syntax should be like:
"D:\Softwares\Analyzer.exe" [DataFile1].dat [DataFile2].dat ... [DataFileN].dat AnalysisFile.pdo"
Currently I have tried to use a FOR loop to scan each *.dat file in a specified folder. (I don't know how many data files in that folder, so I cannot type the filenames directly in the command line)
For example:
#ECHO OFF
FOR /r %%i in (*.dat) DO (
"D:\Softwares\Analyzer.exe" %%~ni.dat TestAnalysis.pdo
)
PAUSE
However, the analysis is carried out on seperate datafiles, and the .exe file will pop-up and open every time when a new .dat file is detected. Is there any way I could use *.dat or any other methods to represent [DataFile1].dat [DataFile2].dat ... [DataFileN].dat in one line seperated by a space (not a new line)?
I have also tried to use #tilte, which does not work as well. Since the .exe window keep pop-up whenever a new .dat file is detected and I have to close each of them in order to continue to next .dat file.
In general, I would like to do an automatic scan in a folder, get the names of the datafiles, and write a command line to call these .dat files in one line.
Any ideas/helps appreciated!!!
try this, remove the word echo if the output is OK:
#echo off &setlocal enabledelayedexpansion
set "line="
for %%i in (*.dat) do set "line=!line! "%%i""
echo "D:\Softwares\Analyzer.exe" %line% TestAnalysis.pdo
The code doesn't work with *dat files with exclams ! in the file name. This may be fixed if needed.
I am facing problems with Unicode named folders. When I drag the folder to the script, it doesn't show the path of the folder properly.
Simple VBScript (this is just a portion of it):
Dim Wshso : Set Wshso = WScript.CreateObject("WScript.Shell")
Dim FSO : Set FSO = CreateObject("Scripting.FileSystemObject")
If WScript.Arguments.Count = 1 Then
If FSO.FileExists(Wscript.Arguments.Item(0)) = true and FSO.FolderExists(Wscript.Arguments.Item(0)) = false Then
Alert "You dragged a file, not a folder! My god." & vbcrlf & "Script will terminate immediately", 0, "Alert: User is stupid", 48
WScript.Quit
Else
targetDir = WScript.Arguments.Item(0)
Wshso.Popup targetDir
End If
Else
targetDir = Wshso.SpecialFolders("Desktop")
Alert "Note: No folder to traverse detected, default set to:" & vbcrlf & Wshso.SpecialFolders("Desktop"), 0, "Alert", 48
End If
If it is a normal path without Unicode characters, it's fine. But in this case:
Directory: 4minute (포미닛) - Hit Your Heart
Then it will show something like 4minute (?) - Hit Your Heart
And if I do a FolderExists it can't find the dragged folder.
Is there any workaround to support Unicode named Folders?
Thanks!
I'll edit if this is not clear enough
This does seem to be a problem peculiar to the Windows Script Host's DropHandler shell extension. Whereas:
test.vbs "C:\포미닛.txt"
C:\WINDOWS\System32\WScript.exe "test.vbs" "C:\포미닛.txt"
both work when typed from the console (even if the console can't render the Hangul so it looks like ?), a drag and drop operation that should result in the same command goes through a Unicode->ANSI->Unicode translation that loses all characters that aren't in the current ANSI code page. (So 포미닛 will work on a default Korean Windows install but not Western.)
I'm not aware of a proper way to fix the problem. You could perhaps work around it by changing the DropHandler for .vbs files in the registry:
HKEY_CLASSES_ROOT\VBSFile\ShellEx\DropHandler\(Default)
from the WSH DropHandler ({60254CA5-953B-11CF-8C96-00AA00B8708C}) to {86C86720-42A0-1069-A2E8-08002B30309D}, the one used for .exe, .bat and similar, which doesn't suffer from this issue. You would also probably have to change the file association for .vbs to put quotes around the filename argument too, since the EXE DropHandler doesn't, to avoid problems with spaces in filenames.
Since this affects argument-passing for all VBS files it would be a perilous fix to deploy on any machine but your own. If you needed to do that, maybe you could try creating a new file extension with the appropriate DropTarget rather than changing VBSFile itself? Or maybe forgo drop-onto-script behaviour and provide a file Open dialog or manual drop field instead.
For anyone landing here from Google...
Bobince's tip lead me to work around this problem by wrapping my vbscript file (myscript.vbs) in a dos batch file (mybatch.bat).
The tip was:
"Seem to be a problem peculiar to the Windows Script Host's
DropHandler shell extension whereas.... the one used for .exe, .bat and
similar... doesn't suffer from this issue."
mybatch.bat contains:
:Loop
IF "%1"=="" GOTO Continue
set allfiles=%allfiles% "%1"
SHIFT
GOTO Loop
:Continue
"myscript.vbs" %allfiles%
You may also find this code from my myscript.vbs to be helpful
For Each strFullFileName In Wscript.Arguments
' do stuff
Next
Based on DG's answer, if you just want to accept one file as drop target then you can write a batch file (if you have it named as "x.bat" place VBScript with filename "x.bat.vbs" at same folder) that just contains:
#"%0.vbs" %1
the # means to not output the row on the display (I found it to show garbage text even if you use chcp 1250 as first command)
don't use double-quotes around %1, it won't work if your VBScript uses logic like the following (code I was using below was from http://jeffkinzer.blogspot.com/2012/06/vbscript-to-convert-excel-to-csv.html). Tested it and it works fine with spaces in the file and folder names:
Dim strExcelFileName
strExcelFileName = WScript.Arguments.Item(0) 'file name to parse
' get path where script is running
strScript = WScript.ScriptFullName
Dim fso
Set fso = CreateObject ("Scripting.FileSystemObject")
strScriptPath = fso.GetAbsolutePathName(strScript & "\..")
Set fso = Nothing
' If the Input file is NOT qualified with a path, default the current path
LPosition = InStrRev(strExcelFileName, "\")
if LPosition = 0 Then 'no folder path
strExcelFileName = strScriptPath & "\" & strExcelFileName
strScriptPath = strScriptPath & "\"
else 'there is a folder path, use it for the output folder path also
strScriptPath = Mid(strExcelFileName, 1, LPosition)
End If
' msgbox LPosition & " - " & strExcelFileName & " - " & strScriptPath
Modify WSH DropHandler ({60254CA5-953B-11CF-8C96-00AA00B8708C}) to {86C86720-42A0-1069-A2E8-08002B30309D} and add this function to convert short path to long:
Function Short2Long(shortFullPath)
dim fs
Set fs = CreateObject("Scripting.FileSystemObject")
Set f = fs.GetFile(shortFullPath)
Set app = CreateObject("Shell.Application")
Short2Long = app.NameSpace(f.ParentFolder.Path).ParseName(f.Name).Path
end function