Location: PHPKode > scripts > wd97template > wd97template/wd97template.class.php
<?php
/**
 * Allows Word 97/2000 templates to be used in a similar way to HTML templates.
 * ie Allows subsititution of fields such as {NAME} defined in a .doc or a .dot
 *
 * Read comments for further instructions.
 *
 * IMPORTANT NOTE
 * You MUST call the destroy() method when you have finished. Else you will be left
 * with a zombi Word process on the server every time the class is used
 *
 * Contact me with comments/suggestions
 *
 * Requires: Windows NT (Easily extended to use DCOM, but not tested).
 * Works with late version PHP3 and better
 *
 * @author Peter Cruickshank - php at krabi dot demon dot co dot uk
 * @copyright This version is free for use/modification so long as my details are retained
 *
 *-----------------------------------------------------------------------------------
 * History
 * May01 Peter Cruickshank Created
 * Jan03 Peter Cruickshank Reformatted for phpDoc. No changes to code
 *
 *-----------------------------------------------------------------------------------
 */


// WORD CONSTANTS ----------------------------------------------------------------------
define("wdReplaceOne",   1);
define("wdReplaceAll",   2);

define("wdStory",        6);

define("wdSectionBreakNextPage",2);

define("wdOrientPortrait", 0);
define("wdOrientLandscape",1);


// THE CLASS ---------------------------------------------------------------------------
class wd97template {
   /**
   * Where to find .dot template files. Must end in a "/" if a value is specified.
   * @var string
   * @access public
   */
   var $path_dot = "";

   /**
   * Where to find .doc files for appending. Must end in a "/" if a value is specified.
   * @var string
   * @access public
   */
   var $path_doc = "";

   /**
   * Where the new file is to be saved. Must end in a "/" if a value is specified
   * @var string
   * @access public
   */
   var $path_save = "";

   /**
   * Word template used to generate base document. Read-only
   * @var string
   * @access public
   */
   var $template = "";

   /**
   * Filename of saved document. Empty til document has been saved. Read-only
   * @var string
   * @access public
   */
   var $filename = "";

   /**
   * Diagnostic error message containing reason for failure. Read-only
   * @var string
   * @access public
   */
   var $error_msg = "";

   /**
   * Word COM object
   * @var object
   * @access private
   */
   var $word;
   /**
   * Holds search and replaces til ready for processing
   * @var array
   * @access private
   */
   var $fields = array();

   /**
   * Constructor
   *
   * @param string $t - the template file to use. Empty if a blank document is to be generated
   */
   function wd97template($t) {
       $this->template = $t;
   } // wd97template


   /**
   * Build up list of field subsitutions.
   *
   * Note that no other action is carried out here - use process() once the list is complete.
   * It is possible to repeatedly carry out several assigns, followed by process()es.
   *
   * @access public
   * @param array $a - associative array of fieldnames and values to be assigned, eg "FORENAME" => "Peter"
   * @return void
   */
   function assign($a) {
      while (list($var, $val)=each($a)) {
         $this->fields[$var]=stripslashes($val);
      }
   }

   /**
   * Creates the word instance ready for processing
   *
   * @access public
   * @return boolean If false, error_msg has diagnostic
   */
   function create() {
      $res=true;

      if (!$this->word=new COM("word.application")) {  // For DCOM - add the server name as 2nd parameter (not tested)
         $this->error_msg = "Cannot start Word for you";
         return false;
      }

      $fp = $this->path_dot . $this->template;
      if (!file_exists($fp)) {
         $this->error_msg = "Could not find template file ".$fp;
         return false;
      }

      if (!$this->word->Documents->Add($fp)) {
         $this->error_msg = "Could create word file from ".$fp;
         return false;
      }

      $this->word->visible = 1; // Makes no difference, but left in cos its in all the examples

      return true;

   } // create


// THE FOLLOWING FUNCTIONS DEPEND ON THE EXISTENCE OF A VALID OBJECT IN $this->word
// - ie that the ->create() method has been called.


   /**
   * Used for misc formatting actions
   *
   * Each action is performed in order, at the current cursor position
   * Which is normally the file end.
   * Unknown actions are ignored.
   *
   * DEPENDS ON THE EXISTENCE OF A VALID OBJECT IN $this->word
   *
   * @access public
   * @param array $fmt List of instructions eg (array( "Orientation" => ??, "InsertBreak" => ??));
   * @return void
   */

   function format($fmt) {
      $this->moveend();
      reset($fmt);
      while (list($k,$v) = each($fmt)) {
         switch($k) {
         case "InsertBreak":
            $this->word->Selection->InsertBreak($v);  // eg wdSectionBreakNextPage
            break;
         case "PageOrientation":
            $this->word->Selection->MoveRight();
            $oSel = $this->word->Selection;
            $oSel->PageSetup->Orientation = $v;
            break;
         default:
         }
      }
   }


   /**
   * Appends file to current document
   *
   * Leaves cursor at *end* of inserted file
   *
   * @access public
   * @param string $f filename of the word document to be appended
   * @return boolean If false, error_msg has diagnostic
   */
   function appendfile($f) {

   $fp = $this->path_doc.$f;

   if ( !file_exists($fp) ) {
   $this->error_msg = "Append file $fp does not exist";
   return false;
   }

   $oDoc = $this->word->ActiveDocument;
   $iEnd = $oDoc->Content->End - 1;

   $oEndRange = $oDoc->Range($iEnd,$iEnd);
   $oEndRange->InsertFile($fp);

   $this->moveend();

   return true;
   } // appendfile


   /**
   * Carry out the replacement of fieldnames
   *
   * List of assigned fields is cleared.
   *
   * @access public
   * @return void
   */

   function process() {
      $oFind = $this->word->ActiveDocument->Content->Find;

      //Corresponding VBA is:
      //expression.Execute(FindText, MatchCase, MatchWholeWord, MatchWildcards, MatchSoundsLike, MatchAllWordForms,
      //                             Forward,   Wrap,Format, ReplaceWith, Replace)
      while (list($var, $val)=each($this->fields)) {
         $oFind->Execute("{".$var."}",  true,   true,           false,          false,           false,
                                     true,      true,false,  $val,        wdReplaceAll);
      }
      $this->fields = array();   // Clear out s&r ready for next time
   } // process


   /**
   * Save file, deleting any previous copy
   *
   * To Do:
   * Create backup copy before write.
   *
   * @param string $f full word document to be saved (needs ".doc")
   *
   * @access public
   * @return boolean
   */
   function saveas($f) {

      if ( file_exists($this->path_save.$f) ) {
         if ( !unlink($this->path_save.$f) ) {
            $this->error_msg = "Could not delete previous versions of $f";
            return false;
         }
      }

      $this->word->ActiveDocument->SaveAs($this->path_save.$f);

      $this->filename = $f;
      return true;
   } // end saveAs


   /**
   * Moves selection to file-end (for formatting and after appends).
   *
   * @access private
   * @return void
   */
   function moveend() {
      $this->word->Selection->MoveEnd(wdStory);
      $this->word->Selection->MoveRight();
   }


   /**
   * Gets rid of Word process on server
   *
   * MUST BE CALLED otherwise the process will sit on the server forever.
   *
   * @access public
   * @return void
   */
   function destroy() {
      $this->word->Quit();
   } // destroy

} // end class

?>
Return current item: wd97template