TinyButStrong - the PHP Template Engine
Categories > Your tips & tricks >

delete colmuns in a Ms Word document

The forum is closed. Please use Stack Overflow for submitting new questions. Use tags: tinybutstrong , opentbs

By: Skrol29
Date: 2012-02-17
Time: 00:08

delete colmuns in a Ms Word document

Hello,

Here is a TBS plug-in that enhances OpenTBS and enables you to delete some columns in a table of an Ms Word documents.

tbs_plugin_delcol.php
<?php

/*

This TBS plug-ins enables you to delete the columns you want in any table of an Ms Word Document.
It is supposed to be used with OpenTBS.

Version 1.00
Skrol29, 2011-10-07

Installation:
--------------

  $TBS = new clsTinyButStrong;
  $TBS->Plugin(TBS_INSTALL, OPENTBS_PLUGIN);
  $TBS->Plugin(TBS_INSTALL, DELCOL_PLUGIN);

Use:
----

You have to put a TBS field anywhere inside the table with the following parameters:
The field will be erased and the specified columns will be deleted.

* ope=delcol
* colnum   = the column numbers to delete, separated with commas (first colmun is number 1).
* colshift = (optional) if parameter "colnum" has only on value then "colshift" extends the number of columns to delete to the left of to the rigth.
  
Both parameters "colnum" and "colshift" can contain  [val] and [var] fields.
  
Examples:
---------

[onload;ope=delcol;colnum=2,4,6]         => will delete columns {2,5,6}
[onload;ope=delcol;colnum=2;colshift=2]  => will delete columns {2,3,4}
[onload;ope=delcol;colnum=2;colshift=-1] => will delete columns {1,2}

[onload.col_to_delete;ope=delcol;colnum=[val];colshift=2] => will delete 3 colmuns staring to column number $col_to_delete


*/

define('DELCOL_PLUGIN','clsTbsDeleteColumn');

class clsTbsDeleteColumn {

  function OnInstall() {
    $this->Version = '1.00'; // Versions of installed plug-ins can be displayed using [var..tbs_info] since TBS 3.2.0
    return array('OnOperation');
  }

  function replaceTbsFields($Prm, $Value) {
    $this->TBS->meth_Merge_AutoVar($Prm, true);
    $Prm = str_replace($this->TBS->_ChrVal, $Value, $Prm);
    return $Prm;
  }
 
  function OnOperation($FieldName,&$Value,&$PrmLst,&$Txt,$PosBeg,$PosEnd,&$Loc) {

    if ($PrmLst['ope']!='delcol') return; // activated only if delcol parameter is used

    if (!isset($PrmLst['colnum'])) return;
 
    // List of columns converted into an array
    if (is_array($Value)) $Value = implode(',', $Value);
   
    $col_lst = $this->replaceTbsFields($PrmLst['colnum'], $Value);
 
    $col_lst = str_replace(' ', '', $col_lst);
    if ( ($col_lst=='') || ($col_lst=='0') ) return false; // nothing to do
   
    $col_lst = explode(',', $col_lst);
    $col_nbr = count($col_lst);
   
    for ($c=0; $c<$col_nbr; $c++) $col_lst[$c] = intval($col_lst[$c]); // Conversion into numeric
 
    // Add column by shifting
    if (isset($PrmLst['colshift'])) {
      $col_shift = intval($this->replaceTbsFields($PrmLst['colshift'], $Value));
      if ($col_shift<>0) {
        $step = ($col_shift>0) ? -1 : +1;
        for ($s = $col_shift; $s<>0; $s = $s + $step) {
          for ($c=0; $c<$col_nbr; $c++) $col_lst[] = $col_lst[$c] + $s;
        }
      }
    }

    // Delete the TBS field
    $Txt = substr_replace($Txt, '', $PosBeg, $PosEnd - $PosBeg + 1);

    // Look for the source of the table
    $Loc = clsTbsXmlLoc::findElement($Txt, 'w:tbl', $PosBeg, false);
   
    if ($Loc===false) return false;
    $Src = $Loc->GetTxt();

    $this->deleteElements($Src, 'w:tblGrid', 'w:gridCol', $col_lst);
    $this->deleteElements($Src, 'w:tr', 'w:tc', $col_lst);

    $Loc->ReplaceTxt($Src);

    return false; // avoid the mergin of the field
   
  }

  function deleteElements(&$Txt, $ParentTag, $Tag, $ColLst) {
 
    $ColLst = array_unique($ColLst, SORT_NUMERIC); // delete double columns
    sort($ColLst, SORT_NUMERIC); // sort
    $ColMax = $ColLst[(count($ColLst)-1)]; // last column to delete
 
    $ParentPos = 0;
    $TotalDelNbr = 0;
    while ($ParentLoc = clsTbsXmlLoc::findElement($Txt, $ParentTag, $ParentPos, true)) {
      $ParentTxt = $ParentLoc->GetTxt();
      $ColNum = 0;
      $ColPos = 0;
      $Continue = true;
      $DelNbr = 0;
      while ($Continue && ($ColLoc = clsTbsXmlLoc::findElement($ParentTxt, $Tag, $ColPos, true)) ) {
        $ColNum++;
        if ($ColNum>$ColMax) {
          // stop the search
          $Continue = false;
        } elseif (array_search($ColNum,$ColLst)===false) {
          // ne deletation
          $ColPos = $ColLoc->PosEnd + 1;
        } else {
          // deleteation
          $DelNbr++;
          $ColLoc->ReplaceTxt('');
        }
      }
      if ($DelNbr>0) $ParentLoc->ReplaceTxt($ParentTxt);
      $TotalDelNbr = $TotalDelNbr + $DelNbr;
      $ParentPos = $ParentLoc->PosEnd + 1;
    }

    return $TotalDelNbr;
   
  }

}

/* An instance of clsTbsXmlLoc representes a location of an XML element (<tag>...</tag>) in a TXT contents.
   Attributes are no
*/
class clsTbsXmlLoc {

  var $PosBeg;
  var $PosEnd;
  var $SelfClosing;
  var $Txt;

  // crate an instance with the given parameters
  function __construct(&$Txt, $PosBeg, $PosEnd, $SelfClosing = false) {
    $this->Txt = &$Txt;
    $this->PosBeg = $PosBeg;
    $this->PosEnd = $PosEnd;
    $this->SelfClosing = $SelfClosing;
  }

  // return the len of the locator
  function GetLen() {
    return $this->PosEnd - $this->PosBeg + 1;
  }
 
  // return the source of the locator
  function GetTxt() {
    return substr($this->Txt, $this->PosBeg, $this->GetLen() );
  }
 
  // replace the source of the locator in the TXT contents
  // update the locator's positions
  function ReplaceTxt($new) {
    $len = $this->GetLen(); // avoid PHP error : Strict Standards: Only variables should be passed by reference
    $this->Txt = substr_replace($this->Txt, $new, $this->PosBeg, $len);
    $this->PosEnd = $this->PosEnd + strlen($new) - $len;
  }

  // search an element in the TXT contents, and return an object if it is found
  static function findElement(&$Txt, $Tag, $PosBeg, $Forward) {

    $PosBeg = clsTinyButStrong::f_Xml_FindTagStart($Txt, $Tag, true , $PosBeg, $Forward, true);
    if ($PosBeg===false) return false;
   
    $PosEnd = strpos($Txt, '>', $PosBeg);
    if ($PosEnd===false) return false;
   
    $SelfClosing = (substr($Txt, $PosEnd-1, 1)=='/');
    if (!$SelfClosing) {
      $PosEnd = clsTinyButStrong::f_Xml_FindTagStart($Txt, $Tag, false, $PosEnd, true , true);
      if ($PosEnd===false) return false;
      $PosEnd = strpos($Txt, '>', $PosEnd);
      if ($PosEnd===false) return false;
    }
   
    $XmlLoc = new clsTbsXmlLoc($Txt, $PosBeg, $PosEnd, $SelfClosing);
   
    return $XmlLoc;

  }
 
}