WinBatch Tech Support Home

Database Search

If you can't find the information using the categories below, post a question over in our WinBatch Tech Support Forum.



Can't find the information you are looking for here? Then leave a message over on our WinBatch Tech Support Forum.

All About Template Files


Processing Template Files in WinBatch


One powerful trick in computing is the use of template files. Template files can be used when you need to produce a large number of files which are very similar but have different content.

A template file is a file what is similar to the desired output file, except that certain placeholders are put into the file instead of the parts of the file that change. The files produced can be nearly any sort of text file. For example, this site World Wide School Library, with maybe 40,000 web pages, is all produced from a small number of different template files.

For a example we can refer to, here is a small template file that we can work with.

Hello {{name}}

The weekly diskscan has examined your used diskspace and
your {{diskspace}}MB is {{overunder}} quota.

This may be, for example, a small report that is sent out to all network users of some department having disk space problems. Of course it could be a lot fancier, or maybe even a HTML page for HTML email.

In any case you can note that there are three {{placeholders}} in the file. The theory is that instead of placing the entire message in a program, a template file can be produced, and a program written to use the template file to produce a new file with the desired contents.

WinBatch can easily process template files. There are a large number of different ways to do it. Two of the better ones are known as the "StrReplace" method and the "BinaryTag" method.


The StrReplace method is quick and easy, and works in perhaps most of the cases you may come across. The BinaryTag method is just a bit more complicated, but is also much more powerful. BinaryTag will be discussed in the next section.

StrReplace Simple Sample
Mass file generation

The StrReplace method is based on the WinBatch StrReplace function.

The StrReplace function can almost instantly change all the occurrences of a string to a different string. So it is used to convert the desired {{placeholders}} to the desired values.

To make this work in an example, we will use three files, Template.txt, InputData.txt, and a WBT file that we'll call StrReplace.wbt

First the template file again

Hello {{name}}

The weekly diskscan has examined your used diskspace and
your {{diskspace}}MB is {{overunder}} quota.

Secondly, the input data file
John Doe~1234
Suzy Simpson~873
Peter Paulson~762
Harvey Wallbanger~875

And finally the script
; This program will create a number of files based on the lines
; in the "inputdata.txt" file.  The output files will be
; named Msg0001.txt Msg0002.txt and so on.

; Define template file name to use

; Define input file

; A counter is initialized to zero for our output file names

; A standard FileOpen to read in the input file, line by line

; We process each line of the input file in this while loop
While 1
   ; Standard file read code, checking for the EOF condition.
   If line=="*EOF*" Then Break

   ; Now we break the data out of a line of the input file
   ; And clean the data up in case there are extra spaces around it

   ; We'll assume everybody's quota is 1000MB
   If DiskSpace > 1000

   ; Increment output file name count
   ; and build an output file name

   ; Now the magic starts.
   ; First we read the template file into our variable

   ; And the StrReplace's to modify the data


   ; And the file is written out to the desired filename

EndWhile      ; Repeat for each line of the file

; Close file

; All Done

If you copy and paste this example and run it, it will produce four files, Msg00001.txt, MSg00002.txt, Msg00003.txt, and Msg00004.txt. If you examine the contents of a file, it will look like....

Hello John Doe

The weekly diskscan has examined your used diskspace and
your 1234MB is over quota.

...and you can see the various {{placeholders}} now contain data from the input file.


Useful Example
HTML Slideshow for JPG files

In this example a HTML slide show is created out of a directory containing a number of JPG files. We will take a simple HTML template file and use it to create a slideshow containing all the JPG's in some indicated directory.

First of all, here is a template file. If you wish you can make it more elaborate later.

   <body bgcolor="#000000" text="#FFFFFF" LINK="#FFFF00" VLINK="#FFFF00" ALINK="#00FFFF">
         <a href="{{PREVLINK}}">Previous</a> <a href="{{NEXTLINK}}">Next</a>
         <img src="{{IMAGE}}">
         <!-- Or perhaps to force image sizing use the line below instead of the line above.
         <img src="{{IMAGE}}" width="400" height="300">
         <font color="#00FFFF">{{IMAGETITLE}}</font>
In this simple HTML template file there are just four different types of placeholders. They are:
Used for both the HTML page title, and the title on the image on the page. It is simply the "root" part of the image filename, the part without the path information and without the .jpg extension.

This is the full filename to the file. If you plan to place these pages on a real website, you would modify this to be the URL to the image file.

The name of the previous page to link to.

The name of the next page to link to.

Now to build the slide show, this code can be used. Be sure to fix the pointer to the JPG directory, or perhaps insert an AskDirectory function instead.
;THIS LINE will REQUIRE fixing for your system
JPGDir="C:\JPGS\"   ;Directory of a bunch of JPG files.  Put \ on end

;This line will probably work as-is.
HTMLDir="Pages\"    ;Directory to place new HMTL files. Put \ on end

;If destination directory does not exist, make it
If DirExist(HTMLDIR)==@FALSE Then DirMake(HTMLDir)

;Define the template file filename

;Now we collect a list of all the JPG files in the JPGDir directory
;And count how many there are

;Now we build one HTML page per JPG file for the slide show.
For xx= 1 To JPGCount

   ;Extract a JPG filename from the list

   ;Using just the root part of the file name for the title.
   ;If the JPG's are named something reasonable, this should work.
   ;Now, based on the title, make a HTML file name
   ;And expand the HTML file name to a fully pathed file name 
   ;to the desired html file

   ;Now we want to work out what html files the PREVIOUS and NEXT
   ;links should point to.  First we do the obvious ones
   PrevNum = xx - 1
   NextNum = xx + 1
   ;Then we fix the numbers for the first and last images
   If xx==1 Then PrevNum=JPGCount
   If xx==JPGCount Then Nextnum=1

   ;And we then build the HTML filenames for the previous and next
   ;links, based on the numbers set just above.

   ;And now the StrReplace Magic occurs
   ;First we read the template file into a variable
   ;Then do our StrReplace's to edit the template
   ;And we write the edited data out

;And use ShellExecute to display the first HTML file in the user's
;default browser

;And we are all done.


If you try this, you can see that you can create many HTML pages practically instantly. And it makes a nice little slide show.

The StrReplace function may be able to do all the template file processing you will ever need. However... You may have more demanding requirements. Thus the BinaryTag method.


Whileas the StrReplace functions discussed previously changes every occurence of a {{placeholder}} in a template file to the same replacement string, there are cases where more intelligence might be desired. These "more intelligent" placeholders are called "tags", the idea being that it tags a spot where special processing should occur. Thus the family of functions are called the BinaryTag functions. For example, if you were writing a book, you could place a {{CHAPTER}} tag at the beginning of each chapter. The idea being that the first {{CHAPTER}} tag would be replaced by "Chapter I", the next one by "Chapter II", "Chapter III", "Chapter IV", and so on, a different, intelligent replacement string each time.

Of course a given template file may have all sorts of different tags in it.

There is no particular "magic" about rooting through a file, looking for various {{tags}} and processing them accordingly. However, the BinaryTag functions allow you to do this in a fast, efficient, clean manner, with a minimum of code.

It turns out that, these days, the production of HTML files is the most common use of the BinaryTag functions, however these concepts can be used for any kind of template file processing. In deference to the wide usage of HTML template files, we will use HTML based examples to help explain how to use it.

First of all, there are four primary BinaryTag functions. These are:

Sets up a program to perform a series of BinaryTag operations on a template file that has been read into a Binary Buffer.

Locates the next tag in the file.

Grabs the contents of a tag so it can be examined and processed

Replaces a previously found tag with the desired placement information.

The basic sequence of operations goes like this:
  • Load a template file into an oversized BinaryBuffer.
  • Perform a BinaryTagInit to set up for rummaging through the buffer.
  • Then the following is repeated until no more tags are found.
    • Do a BinaryTagFind to find the next tag.
    • BinaryTagExtr to retrieve the contents of the tag.
    • Tag is examined by the program.
    • Optionally, replacement text is built and a BinaryTagRepl replaces the tag with desired replacement text.
  • When complete, the modified buffer may be written to a file.
  • The process may be repeated to generate a different file.
Next, we will cover three simple examples to get the basic comprehension of the BinaryTag functions straight, and then a real one where the power of the BinaryTag functions is more fully exposed.

BinaryTag Example 1
Make a HTML filename/title database

In this first example, the idea is that we will point the script to a directory full of HTML files, and the script will root through all the HTML files in the directory and extract the title field from the HTML and build a tab delimited text file that relates the HTML file names to the HTML title fields. Thus...
;This script builds a tab delimited text file containing
;HTML file names and the title fields from the HTML documents

;Point this variable to a directory full of HTML files
htmldir="C:\MyHtmlDocs\"   ;remember \ on end

;Define output file name for the text file

;This gets a tab delimited list of all the HTML file names

;This counts them to see how many we have

;Opens the output file to receive the information we
;are going to write to it

;Allocate a BinaryBuffer BIGGER than any HTML file.  Guess.
bbsize=100000   ; must be bigger than any html file

;For each HTML file in our list
For xx=1 To HtmlCount
    ;Get next file to work with from list.  It will be a 
    ;fully qualified filename with path and everything

    ;Work out just the plain filename without the path info

    ;Read the file into our Binary Buffer

    ;Initialize the BinaryTag operations.  We will use
    ;<title> for the beginning tag and </title> for the
    ;ending tag.

    ;We do not expect to find more than one tag, so there
    ;is no loop set up to rummage thru the whole file

    ;Find the tag

    ;If no tag found, then document does not have a title    
    If structure=="" Then title="***No Title Found***"
    ;else extract contents of tag
    Else title=BinaryTagExtr(structure,1)
    ;Write filename and extracted title to our file

    ;Clear out BinaryBuffer for reuse
    ;Then do it again for the next file

;Free the BinaryBuffer

;Close the file

;Display the file
;All done


BinaryTag Example 2

This example is similar to the previous one, except that the BinaryTagRepl function is now brought into play, and edited copies of the source files are actually created. Try it with a large directory of HTML files. You will see that it is incredibly fast.
;This script will edit HTML files to make the title
;of the HTML document all UPPERCASE.

;Point this variable to a directory full of HTML files
htmldir="C:\MyHtmlDocs\"   ;remember \ on end  

;This will make a folder to place the edited HTML files
If DirExist(outputHTMLDir)==@FALSE Then DirMake(outputHTMLDir)

;Make a "mask" for the FileMapName function to transmorgify
;the input filename to an output file name.

;Get the list of HTML files

;Count them

;Allocate a BinaryBuffer to work with
bbsize=100000   ; must be bigger than any html file

;For each file in the list
For xx=1 To HtmlCount

    ;Get the next HTML file name

    ;Create the output file name for later

    ;Read the HTML file into the buffer

    ;Initialize the BinaryTag logic

    ;Again, there is no loop here as we only expect
    ;the <title> tag to appear once

    ;Find the <title>xxx</title> tags.

    ;Assuming we found a set of title tags...
    If structure  != ""
       ;Extract text between the tags
       ;UPPERCASE the title tag
       ;Now we want the <title> </title> around it.  So
       ;we have to add them back in to the replacement string
       ;Update the BinaryBuffer with the new data
    ;Write the edited file out
    ;Clear out the BinaryBuffer for next time

;Free the buffer

Message("All Done","Examine files in the output directory")


BinaryTag Example 3
Strip HTML tags from HTML files

In this example we actually work thru the entire contents of an HTML file, several times actually, to strip the HTML from the file and to leave a plain text document. Depending on your HTML files, your luck with this code may vary.
; In this example the BinaryTag functions are used to locate and
; strip HTML tags from a html file, and to produce a text only
; file. 

;In this example, set the htmlfile variable to any handy HTML file

;And set the textfile variable to a suitable output filename


;Per usual, allocate an oversize BinaryBuffer.  Not strictly
;necessary in this case as we will be reducing filesize
;rather than enlarging it.

;Read the HTML file into the BinaryBuffer

;Pass 1.  Strip HTML comments
;In this first pass thru the file, we remove the HTML comments
;as the HTML comments may contain items that may confuse
;the BinaryTag functions.  Mostly items that look like end tags
;that we will use later.

;Initialize BinaryTag operations

;Now we have a simple while loop, working thru the entire
;HTML file
While 1
   ;Find next HTML comment
   ;If not found, exit loop
   If structure=="" Then Break
   ;If found, replace comment with an empty string

;Pass 2.  Strip remaining HTML 
;Now that the confusing HTML comments are removed, now we
;go after the normal HTML in the file

;Initialize the BinaryTag logic again, with the 
;normal HTML < and > tags

;And another loop, similar to above to remove
;all the html from the file
While 1
   If structure=="" Then Break

;Now at this point the job is basically done.  However
;the stripped file then usually contains a large 
;number of blank lines where HTML used to be, and this
;makes the resulting file a tad messy.  So now there
;is a little cleanup work.

;Convert line endings to @LF to make processing easier
;and also to handle UNIX-style HTML files properly

;Pass 3.  Remove spaces at ends of lines

;This replaces all occurrences of {SPACE}@LF with
;plain @LF, thus removing spaces at the ends of lines.
;The process is repeated until there are no remaining
;spaces at the end of the line
While BinaryReplace(bb,StrCat(" ",@LF),@LF,@TRUE) !=0

;As above, except for tabs this time
While BinaryReplace(bb,StrCat(@TAB,@LF),@LF,@TRUE) !=0

;Pass 4. Remove extra line endings
;In this pass we remove white space between lines,
;simply by replacing duplicate adjacent @LF's with
;a single one.  Similar to the above
While BinaryReplace(bb,StrCat(@LF,@LF),@LF,@TRUE) !=0

;Pass 5.  Getting a normal file back
;Restore normal DOS @CRLF line endings

;Pass 6
;HTML has some special character string representations.
;The code below picks up a few of the more common ones,
;and changes them back into human readable text.

;Convert some typical HTML special character representations
BinaryReplace(bb,"&nbsp;"," ",@FALSE)

; Write out results

;Free the buffer

;Display converted file

BinaryTag Example 4
The Full Deal

In this example we expose some of the full power of the BinaryTag functions, wherein they allow the scripts to make decisions based on the contents of the tags. The important concept here is that some of the programming shifts from the WinBatch script itself, which can be relatively simple, to the file being worked on.

For this example we will use the following html file. Note that there are various {{ and }} tags contained within it that have all sorts of additional information embedded within the tags. Save this file as WhereAmI.html in any convenient spot.


       Quick Orientation

   <body bgcolor="{{randomcolor LIGHT}}">


   <a href="">
       <img align=right 
         alt="Lost in space.  Near outer event horizon." 
      |<img align=right
         alt="South of the Great Wall.  Somewhat north of the Persens-Pisces Chain." 
      |<img align=right
         alt="In non-descript galactical star agglomeration approximately midway between the larger 
         Coma and Persens Clusters." 
      |<img align=right
         alt="Near a smaller group of stars in the general vicinity of the Virgo cluster." 
      |<img align=right
         alt="Within a smaller spiral armed galaxy near the Magellanic Clouds." 
      |<img align=right
         alt="Eastern arm, so-called 'Milky Way' galaxy." 
      |<img align=right
         alt="Eastern arm of the so-called 'Milky Way' galaxy, on a small blue-green planet currently
         in orbit around a mid-life star locally known as 'The Sun'." 
      |<img align=right
         alt="Near Alpha Centauri, on a small blue-green planet currently in orbit around a mid-life
         star locally known as 'The Sun'" 
      |<img align=right
         alt="Near Alpha and Proxima Centauri, on a small blue-green planet currently in orbit around
         a mid-life star locally known as 'The Sun'" 
      |<img align=right
         alt="Third planet out.  Note planet with concentric rings.  Not that one."  
      |<img align=right
         alt="Someplace surface or in orbit around small planet.  Local name is 'Earth'." 
   <h1>Current Location</h1></a>
   <h1>Local Time</h1></a>

   <br clear=all>
   <hr  color="{{randomcolor DARK}}" size=4 width="50%">

   Sensors detect <font size="+1"><b>
       {{PICKONE Mild|Urgent|Immediate|Emergency|Dire}}
		 </b></font> need for caffeinated beverages.
   <font size="+1"><b>Be Alert!</b></font>  We need more lerts.
   Your lucky color for today is <font size="+1"><b>
      {{PICKONE Chartuese|Magenta|Puce|Pumpkin|Cerise|Cerulean|Cyan|Aquamarine|Carmine|Fuchsia}}
   Your lucky number for today is <font size="+1"><b>
      {{PICKONE 1|2|3|4|5|6|7|8|9|pi|e|The Golden Mean|c<superscript>2</superscript>|The Fine Constant}}
   <hr  color="{{randomcolor DARK}}" size=4 width="50%">
   This message has been brought to you by the letter <font size="+3">&nbsp;&nbsp;
      {{PICKONE A|B|C|D|E|F|G|H|J|K|M|N|P|Q|R|S|T|U|V|W|X|Y|Z}}


If you study the above pseudo-html template file and locate the various {{tags}} you will find a small assortment. These are:
Has no parameters. Used to place current date.

Takes one parameter, LIGHT or DARK. Chooses a random color, but biased either light or dark, as specified in the parameter.

The PICKONE keyword is followed by a |-delimited list. One item of the list is chosen at random to replace the entire tag.

This is similar to PickOne, except that it expects a number of HTML <img src=> tags with alt= text contained within the tag. An image is selected and used to replace the entire tag. The alt= text embedded within the image tag is saved for future use....

This tag is replaced by the alt= text saved by the PickImageSaveAltText tag processing.

So now we have a HTML template file with a few weird {{tags}} in it. The beauty of this is that this file can be processed almost instantly, and an unlimited number of similar files can be built using the same tags or others that you make up. Once you get your tag processing script going, you can make all the different template files you want and don't have to alter the main script unless you decide to define some new sort of tag.

In any event here is my overly commented version of the processing script...

;In this example the variable UseHtmlFile
;points to the template HTML file.

;Tempfile points to a scratch file used
;later to save the modified data

;This example uses a number of #defined
;functions/subroutines.  We define these
;at the end of the example. Most of these
;functions below define what processing is
;to get done for each keyword. In any event
;we gosub the subroutine to get all the
;#DefineFunctions and #DefineSubroutines
;defined now.
GoSub DefineFunctions

;Now that all the helper functions are defined,
;we cover the main processing part of the script.

;BinaryAlloc is used to obtain a
;BinaryBuffer of a size greatly in 
;excess of any reasonable HTML page.

;BinaryRead is used to read the entire
;template file into the allocated

;It begins to get interesting here.
;BinaryTagInit is used to define the
;buffer in question, bb, and the start
;tag {{ as well as the end tag }}.
;BinaryTagInit returns a special value
;that we call a structure. WIL uses the
;structure to keep track of what is
;going on.

;while @TRUE is simply a cute trick that
;means loop forever – at least until
;a break statement elsewhere causes the
;loop to exit
While @TRUE
   ;The BinaryTagFind function locates
   ;the next tagged keyword. It knows
   ;where to start from the information
   ;passed to it in the "structure" variable,
   ;and it also saves updated information in
   ;the structure variable.
   ;If the structure variable comes back
   ;from the BinaryTagFind as a null string,
   ;then no more tagged keywords were found
   ;and it is time to break out of the loop   
   If structure=="" Then Break
   ;The BinaryTagExtr function extracts the
   ;text in between the {{tags}}. Leading and
   ;trailing whitespace is deleted.
   ;In addition, the 1 option indicates that
   ;tabs and line terminators should be
   ;removed and spaces inserted if required.

   ;At this point we’re going into the deep
   ;end. In addition to the keyword we
   ;alluded to previously this code also 
   ;allows parameters behind the keyword.
   ;For example something like {{DORANDOM 9}}
   ;is possible (meaning, I suppose, a
   ;random number between 0 and 9) We
   ;extract the real keyword DORANDOM into
   ;the wbcmd variable and then in the next
   wbcmd=StrLower(ItemExtract(1,wbdata," "))

   ;...using sleight of code, we now extract
   ;the remainder of the wbdata variable
   ;into the wbparams variable. In the case
   ;of the {{DORANDOM 9}} example it would be 9.
   ;If there was nothing behind the keyword
   ;it would be a null “” string.

   ;More magic. Real Magic this time. Instead
   ;of a plethora of IF statements or other
   ;convoluted logic this single statement will
   ;execute the #DefineFunction or #DefineSubroutine
   ;contained in the wbcmd variable. The trick is to
   ;set up functions/subroutines to handle all the 
   ;keywords in your template file. A few sample 
   ;functions are shown below. In theory the function
   ;will examine parameters in wbparams,if any,
   ;and then return the text string that the entire
   ;{{tag xxx}} should be replaced with.
   HtmlValue = %wbcmd% (wbparams)

   ;The BinaryTagRepl takes the string in the
   ;HtmlValue variable and uses it to replace the
   ;tagged keyword (such as {{DORANDOM 9}} in our
   ;running example.). The structure variable is
   ;also updated with new information.

;The EndWhile just tells the while loop to
;loop again to process the next tag

;When no more tags are found, a break statement breaks
;out of the while loop and execution continues here

;The BinaryWrite writes out the modified
;HTML file to an outputfile

;The memory used by the BinaryBuffer is now returned to the system.

;And then we display the page

;At the point the script is actually done.  Below
;are the various #DefineFunctions and #DefineSubroutines
;that make this all work.  In addition to the ones used
;by the example a few other handy functions are included.

;* Definition of Functions and Subroutines for BinaryTag *;
;* keywords.  This code has been Gosub'ed from above     *;

   ;The VALUE subroutine is the easiest and
   ;perhaps the most handy of all. It takes a tagged
   ;keyword like 
   ;{{VALUE FRED}}
   ;and substitutes the global current value of the 
   ;variable FRED. 
   #DefineSubroutine VALUE(valueX)
      If IsDefined(%valueX%)
         subretvar = %valueX% 
         subretvar="???subretvar error %valueX% ???"
      Return (subretvar)
   ;The DATE function is also a no-brainer.
   ;Its take a tagged keyword of {{DATE}}
   ;and substitutes today’s time and date.
   #DefineFunction Date(dummy)
      Return (TimeDate())
   ;The purists would holler if we did not have a
   ;DORANDOM example as referred to above.
   #DefineFunction DORANDOM(Randmax)
      Return (Random(RandMax))

   ;The PICKONE function receives the choice list from the
   ;tag as a single variable called choices.  It chooses
   ;one of the choices at random and returns it.
   #DefineFunction PICKONE(choices)
      ;Count how many different choices are available
      ;pick a random number in the correct range
      ;return that particular choice
      Return ItemExtract(pick,choices,"|")

   ;This function generates a random color like #123456
   ;and returns it, based on a preference for a DARK or LIGHT
   #DefineFunction RandomColor(type)
      If type=="DARK" Then offset=0
      Else offset=8
      For i=1 To 6
      Return color

   ;PickImageSaveAltText is similar in concept to the PICKONE
   ;function, except it has the added complexity of parsing out
   ;the alt= text in the image tag and saving it away in 
   ;a variable.  #DefineSubroutine is used instead of #DefineFunction
   ;as we need to save a persistent copy of the variable away.
   #DefineSubroutine PickImageSaveAltText(choices)
      DaChoice= ItemExtract(pick,choices,"|")
      ;Scoop up and save alt text for a little later
      If x!=0
         If y!=0
      Return DaChoice

   ;The companion function to PickImageSaveAltText, also a
   ;#DefineSubroutine, that just returns the value of the
   ;saved variable containing the alt= text.
   #DefineSubroutine SavedAltTextFromImage(dummy)
      Return SavedAltText



The theory is that you should copy and paste this code into WinBatch Studio and make it work. Then play around with it, changing perhaps both the code and the template file and see what you can make work.

In any event it is hoped that by studying this document you can imagine things you can do with template file processing. Perhaps just using the StrReplace method, or perhaps even getting into modifying one of the above scripts to do your own BinaryTag processing.

Good Luck.

Article ID:   W16293
File Created: 2010:02:17:10:58:07
Last Updated: 2005:02:18:11:19:39