By using .bat and .vbs. How it's possible to print first page from each of 1000 PDFs?
The only working solution, which I found is:
Option Explicit
Const FILE_TO_PRINT = "n:\xxx\xxx\xxx\xxx\xxxx.PDF"
Dim shl
Dim fldr
Dim files,file
Set shl = CreateObject("Shell.Application")
Set fldr = shl.Namespace("n:\HEAT06\BAA Cards\66712\20161103\")
Set files = fldr.Items
For Each file in files
If LCase(file.Path) = LCase(FILE_TO_PRINT) Then
file.InvokeVerbEx("Print")
End If
Next
Set shl = Nothing
Set fldr = Nothing
Set files = Nothing
WScript.Quit
it's does work, BUT it will print whole document, when I need only first page.
Attached a VBS I wrote some years ago that will print the first page of all files you drop on it to the default printer. You may change it to that what you need. If you use it with drag & drop, keep in mind, that you have to drag the marked files from the first or last file in order to get the printouts sorted in the way you marked the files. HTH, Reinhard
'//Print first page of pdfs
set WshShell = CreateObject ("Wscript.Shell")
set fs = CreateObject("Scripting.FileSystemObject")
Set objArgs = WScript.Arguments
if objArgs.Count < 1 then
msgbox("Please drag a file on the script")
WScript.quit
end if
'contact Acrobat
Set gApp = CreateObject("AcroExch.App")
gApp.show 'comment or take out to work in hidden mode
'open via Avdoc and print
for i=0 to objArgs.Count - 1
FileIn = ObjArgs(i)
Set AVDoc = CreateObject("AcroExch.AVDoc")
If AVDoc.Open(FileIn, "") Then
Set PDDoc = AVDoc.GetPDDoc()
Set JSO = PDDoc.GetJSObject
jso.print false, 0, 0, true
gApp.CloseAllDocs
end if
next
gApp.hide : gApp.exit : Quit()
MsgBox "Done!"
Sub Quit
Set JSO = Nothing : Set PDDoc = Nothing : Set gApp =Nothing : Wscript.quit
End Sub
after installing Ghostscript you can use the following code (open a notepad and after saving it change the extension to .bat). You have to place the .bat file in the same folder you have the PDFs you want to print.
The code is (gswin64c.exe may change if you have a newer version of Ghostscript)
for %%I in (*.pdf) do "C:\Program Files\gs\gs9.55.0\bin\gswin64c.exe" -dSAFER -dNOPAUSE -dBATCH -sDEVICE#pdfwrite -sOutputFile#"%%~nI-page1.pdf" -dFirstPage#1 -dLastPage#1 "%%I"
Your question is very old but hopefully this will avoid someone else spending hours like I just did to solve it haha
Related
I was looking for a way to move the 5 oldest modified files in a folder to a different folder.
I came across some helpful pieces of code and I revised it to this:
Dim files
Dim startFolder
Dim destinationFolder
Dim oldestFile
Dim file
Dim FSO
startFolder = "C:\logs\current"
destinationFolder = "C:\logs\backup"
Set FSO = CreateObject("Scripting.FileSystemObject")
Set files = FSO.GetFolder(StartFolder).files
Set oldFiles = CreateObject("System.Collections.ArrayList")
If files.Count <= 5 Then
WScript.Quit
End If
For i = 0 To 4
Set files = FSO.GetFolder(StartFolder).files
Set oldFiles = Nothing
For Each file In files
If Not IsObject(oldestFile) Then
Set oldestFile = file
Else
If file.DateLastModified < oldestFile.DateLastModified Then
Set oldestFile = file
End If
End If
Next
WScript.Echo "OLDEST: " & oldestFile.Name
oldestFile.Move destinationFolder & "\" & oldestFile.Name
Next
Basically what it supposed to do is:
loop 5 times,
each time loop through the files and assign the oldest to oldestFile,
move the file to a different location.
However, it doesn't work, it's echoing the first file's name 5 times and move just this one.
I thought I should set the objects to Nothing to start fresh but to no avail.
You need to reset the variable oldestFile at the beginning (or end) of your loop, not the variable oldFiles.
For i = 0 To 4
Set files = FSO.GetFolder(StartFolder).files
Set oldestFile = Nothing
For Each file In files
...
Next
WScript.Echo "OLDEST: " & oldestFile.Name
oldestFile.Move destinationFolder & "\" & oldestFile.Name
Next
Otherwise the value of oldestFile will never change, because even after being moved the referenced file ramains the oldest file compared to the files in the source folder.
I have a system that's running an old FoxPro program which generates 8 character long DBF files. We make a back up of the program folder each day, but at 5pm the program has generated so many of these garbage dbf's that it's a nuisance. I would just set a del *.dbf in the back up script but there are a few dbf with letters in their name that are needed to run the program.
Files are located in F:\Clean This\
Any numerically titled .dbf files need to be deleted
Any alphabetically titled .dbf file should be left alone
Set objFSO = CreateObject("Scripting.FileSystemObject")
objStartFolder = "F:\Clean This\"
Set objFolder = objFSO.GetFolder(objStartFolder)
Set colFiles = objFolder.Files
collide = "ABCEDFGHIJKLMNOPQRSTUVWXYZ"
For Each objFile in colFiles
If UCase(objFSO.GetExtensionName(objFile.name)) = "DBF" Then
num = 1
For num = 1 to 26 'find files with names start with # 0-9
If Left(objFile.Name,1) = Left(collide,num) Then
Wscript.Echo "Save " & objFile.Name
Else If int(Left(objFile.Name,1)) > 0 Then
Wscript.Echo "Delete!"
End IF
End If
Next
End If
Next
As you can tell the If statements can be done better, I'm unsure how to better work it out. The two Wscript.Echo commands are just placeholders because if anything else I can't get find a suitable delete function that would work in a dos environment (I've already tried kill, no).
Suggestions and improvements would be much appreciated!
Use IsNumeric() to check for file names consisting of digits only:
>> For Each sN In Split("abc 123 1O1 101")
>> If IsNumeric(sN) Then
>> WScript.Echo "delete", sN
>> Else
>> WScript.Echo "keep", sN
>> End If
>> Next
>>
keep abc
delete 123
keep 1O1
delete 101
Your check fails, because you use Left() where you should use Mid():
>> collide = "ABCEDFGHIJKLMNOPQRSTUVWXYZ"
>> num = 5
>> WScript.Echo Left(collide,num)
>> WScript.Echo Mid(collide,num,1)
>>
ABCED
D
and even then Left(objFile.Name,1) will look at only the first character of the file name.
Update (wrt comments):
Apply IsNumeric() to the base name:
Dim oFile
For Each oFile In goFS.GetFolder("..\testdata\17817161").Files
WScript.Stdout.Write oFile.Name
If "dbf" = LCase(goFS.GetExtensionName(oFile.Name)) Then
If IsNumeric(goFS.GetBaseName(oFile.Name)) Then
WScript.Stdout.WriteLine " delete"
Else
WScript.Stdout.WriteLine " keep"
End If
Else
WScript.Stdout.WriteLine " ignore"
End If
Next
output:
123.dbf delete
123.txt ignore
abc.dbf keep
I did finally got it working, and here's what the end result was. It works wonderfully and the higher ups and others were rather impress that it worked better than the built in utility of the program we're backing up. Score!
Set objFSO = CreateObject("Scripting.FileSystemObject")
objStartFolder = "..\System Folder"
Set objFolder = objFSO.GetFolder(objStartFolder)
Set DirFiles = objFolder.Files
Dim oFile
For Each objFile in DirFiles
If "dbf" = LCase(objFSO.GetExtensionName(objFile.Name)) Then
If IsNumeric(objFSO.GetBaseName(objFile.Name)) Then
objFSO.DeleteFile(objFile)
End If
End If
Next
What I've created is a script which pulls the Dell Service code, Username, and Computername, from a computer, and compiles that information into a .csv file. This script will be implemented via Active Directory login scripts, so end users wont have to do a thing.
The problem I'm having though, is everytime a person logs on, it collects their information, and adds it to the list. This means my list could just be full of two people who log onto their computer over and over.
What I would like to happen is for the script to search the .csv file for the specific data collected, and if this data exists, to not enter it.
The code I have so far is this:
dim goFS, tsUsers, bFound
set goFS = createObject("Scripting.FileSystemObject")
set tsUsers = goFS.OpenTextFile("\\xxx\Gathering\DataLog.txt", 2, True)
bFound = False
Do Until tsUsers.AtEndOfStream
If 1 = Instr(tsUsers.ReadLine(), sUser) Then
bFound = True
WScript.Quit (0)
Exit Do
End If
Loop
tsUsers.Close
If Not bFound Then
Set tsUsers = goFS.OpenTextFile("\\xxx\Gathering\DataLog.txt", 8, True)
tsUsers.WriteLine sUser
tsUsers.Close
End If
'Get Dell Service Tag Info
set ProSet = GetObject("winmgmts:").InstancesOf("Win32_BIOS")
Set ProSet1 = GetObject("winmgmts:").InstancesOf("Win32_SystemEnclosure")
For each Pro in ProSet
For each Pro1 in ProSet1
ServiceTag=Pro.SerialNumber
exit for
Next
exit for
Next
'get username and computername, could also be asked in a batch
Set oShell = WScript.CreateObject("WScript.Shell")
Set oShellEnv = oShell.Environment("Process")
sComputerName = oShellEnv("ComputerName")
sUsername = oShellEnv("username")
dim filesys, filetxt, getname, path
Set filesys = CreateObject("Scripting.FileSystemObject")
Set filetxt = filesys.OpenTextFile("\\xx\Gathering\DataLog.csv", 8, True, -2)
path = filesys.GetAbsolutePathName("\\xx\Gathering\DataLog.csv")
getname = filesys.GetFileName(path)
filetxt.WriteLine sUsername & ", " & sComputerName & ", " & ServiceTag
filetxt.Close
The problem I'm getting is a runtime error: 800A0036 (Bad File Mode) in location (Line 5, Char 1).
Thanks guys!
Your
set tsUsers = goFS.OpenTextFile("\\xxx\Gathering\DataLog.txt", 2, True)
opens the file ForWriting.
Cf. the same last week
What I've created is a script which pulls the Dell Service code, Username, and Computername, from a computer, and compiles that information into a .csv file. This script will be implemented via Active Directory login scripts, so end users wont have to do a thing.
The problem I'm having though, is everytime a person logs on, it collects their information, and adds it to the list. This means my list could just be full of two people who log onto their computer over and over.
What I would like to happen is for the script to search the .csv file for the specific data collected, and if this data exists, to not enter it.
The code I have so far is this:
'Get Dell Service Tag Info
set ProSet = GetObject("winmgmts:").InstancesOf("Win32_BIOS")
Set ProSet1 = GetObject("winmgmts:").InstancesOf("Win32_SystemEnclosure")
For each Pro in ProSet
For each Pro1 in ProSet1
ServiceTag=Pro.SerialNumber
exit for
Next
exit for
Next
'get username and computername, could also be asked in a batch
Set oShell = WScript.CreateObject("WScript.Shell")
Set oShellEnv = oShell.Environment("Process")
sComputerName = oShellEnv("ComputerName")
sUsername = oShellEnv("username")
dim filesys, filetxt, getname, path
Set filesys = CreateObject("Scripting.FileSystemObject")
Set filetxt = filesys.OpenTextFile("\\xx.xx.xx.xx\Gathering\DataLog.csv", 8, True, -2)
path = filesys.GetAbsolutePathName("\\xx.xx.xx.xx\Gathering\DataLog.csv")
getname = filesys.GetFileName(path)
filetxt.WriteLine sUsername & ", " & sComputerName & ", " & ServiceTag
filetxt.Close
This is the basic script, without the entry checker.
As for an entry checker, this is what I have tried but it doesn't seem to work:
Set objFSO = CreateObject("Scripting.Dictionary")
Set objFile = objFSO.OpenTextFile ("\\xx.xx.xx.xx\Gathering\Dictionary.txt", 8, True)
' Make comparisons case insensitive.
objList.CompareMode = vbTextCompare
' ... code to read user name and assign to variable strNameOfUser.
If (objList.Exists(strNameOfUser) = False) Then
' Add this user to the dictionary object.
objList(strNameOfUser) = True
' Log this unique user name.
objFile.WriteLine strNameOfuser
End If
Any help is appreciated! Thanks!
(1) Your code is messed up: You store a Dictionary in objFSO and then try to invoke objFSO.OpentextFile()
(2) VBScript can't read and append to a file; so ForAppending (8) won't work; you'll have to read-open the file first, gather the info, close it, append-open and append new user info (if necessary)
(3) Using a dictionary is unnecessarily complex: to fill the dictionary you'll have to read the file from start to end, before you can ask the dictionary whether a specific user exists.
While simply reading the file line by line, you can break the reading as soon as you find the user - then close - open & append - close - done.
UPDATE
Item (3) in code:
Dim goFS : Set goFS = CreateObject( "Scripting.FileSystemObject" )
Dim tsUsers : Set tsUsers = goFS.OpenTextFile(sFSpec, ForReading, True)
Dim bFound : bFound = False
Do Until tsUsers.AtEndOfStream
If 1 = Instr(tsUsers.ReadLine(), sUser) Then
bFound = True
Exit Do
End If
Loop
tsUsers.Close
If Not bFound Then
Set tsUsers = goFS.OpenTextFile(sFSpec, ForAppending, False)
tsUsers.WriteLine sUser
tsUsers.Close
End If
Because I'm a pessimistic worrier: How do you plan to cope with more than one user logging in and write-access the file at the same time?
I need to create A set of empty folders, starting at 10, going to 180. This is the script I'm trying to use, but it just creates 10, and nothing else.
Option Explicit
Dim objFSO, objFolder, strDirectory, i
strDirectory = "\path\to\main\folder"
Set objFSO = CreateObject("Scripting.FileSystemObject")
i = 180
While i < 180
Set objFolder = objFSO.CreateFolder(strDirectory & i)
i = i+1
WScript.Quit
Wend
I'm pretty new to VBScript, so maybe the problem is obvious, but I just don't see it. I also tried using a For loop, but that didn't seem to work at all.
Thanks in advance to anyone who reads this.
I have modified your script as follows:
Option Explicit
Dim objFSO, objFolder, strDirectory, i
strDirectory = "C:\Temp\Test\folder"
Set objFSO = CreateObject("Scripting.FileSystemObject")
i = 10 '' <===== CHANGED!
While i < 180
Set objFolder = objFSO.CreateFolder(strDirectory & i)
i = i+1
''WScript.Quit '' <===== COMMENTED OUT!
Wend
With this script, I managed to create 180 folders.