Home Forums General XMetaL Discussion Deleting more than one row from a table Reply To: Deleting more than one row from a table

Derek Read

Reply to: Deleting more than one row from a table

You could integrate the following into the macros for your XMetaL customization (assuming you built it or can modify it). If you don't know how to do that let me know and I'll see if I can make an application-level MCR file that will work for you. In that case I would need to know your table model so you won't have to edit the file. In theory additional logic might be added to try to detect the table model, but I think it is safer as written (putting the onus on you to modify a couple of values for it to work specifically with your model).

As written it is set up to work with CALS (lowercase), which is what DITA uses, as well as some versions of DocBook.

This script should be fairly robust but please test it thoroughly together with your customization before putting onto production machines.
It does not add a toolbar button or menu item, so unless you add those people would likely run this from the Macros toolbar. You could also add a shortcut key when you turn it into a macro.

Pay particular attention to the section “User Configurable Variables” in my comments as some things may need adjustment depending on your table model.

Licensed Materials – Property of JustSystems, Canada, Inc.

(c) Copyright JustSystems Canada, Inc. 2011
All rights reserved.

The sample contained herein is provided to you “AS IS”.

It is furnished by JustSystems Corporation as a simple example and
has not been thoroughly tested under all conditions. JustSystems
Canada, Inc., therefore, cannot guarantee its reliability,
serviceability or functionality.

This sample may include the names of individuals, companies, brands
and products in order to illustrate concepts as completely as
possible. All of these names are fictitious and any similarity to
the names and addresses used by actual persons or business
enterprises is entirely coincidental.

[code]//XMetaL Script Language JScript:
Created: Derek Read, 2011-07-28
Purpose: Allow an author to delete multiple rows in a CALS or HTML table.
Logic:   Restrict the deletion to HTML or CALS only.
        Restrict deletions to the “body” section of the table.
Prompt the user for number of rows to delete.
Starting with the current row delete that number of rows.
After each deletion check if there are more rows after the current
row in order to stop the code from deleting “back up” the table.

This script only works for CALS or HTML. A different solution would
be necessary for other table models.

For HTML or models that use uppercase names changes are necessary,
see next section for details.

Because XMetaL's selection model handles tables in a unique way (to
provide other functionality) this script must prompt the user for the
number of rows to delete. The product itself (ie: xmetal60.exe) would
need to be extended to allow the user to select several rows and delete
them based on that selection.

User Configurable Variables

Some Facts:
DITA – uses the CALS table model with lower case element names.

DocBook – some versions can be configured to use either model and
may use upper case or lower case.

Journalist (XMetaL demo DTD and XSD) – uses uppercase HTML.

Others – you need to know or find out.

SGML DTDs may declare element names in lowercase while NAMECASE
GENERAL (in the SGML declaration) may cause them to be treated as

What You Need to Change:
CALS lowercase: leave the first two variables as they are.
CALS uppercase: change the first two variables to uppercase.
HTML lowercase: change first variable to “tr”.
HTML uppercase: change the first two variables to “TR” and “TBODY”.
var tableRowElem = “row”;
var tableBodyElem = “tbody”;

//Change the following to prompt the user with a different message.
var promptRowsToDelete = “Number of rows to deleten(including the current row):”;

//Probably best for most people to leave everything below as is…
var rng = ActiveDocument.Range;
var deletedTheLastRow = false;

  Next two ifs check to see that we are in fact inside a table body,
  silent failure should give most people a clue they “can't do that”
  which includes running the script outside a table and running the
  script when they are inside a thead or tfoot (examples) if the DTD
  allows those.
if (rng.InContextOfType(“table”)) {
var inContextOfType_TBody = false;
var bodyXPath = “ancestor-or-self::” + tableBodyElem;
var bodyNodes = rng.ContainerNode.getNodesByXPath(bodyXPath);
if (bodyNodes.length > 0) {
var numRows = Application.Prompt(promptRowsToDelete,”1″);
//Turn off formatting. With this enabled deleting parts of a table
//will cause a reformat and that can be slow.
ActiveDocument.FormattingUpdating = false;
//No need to check if the user entered a number. JScript should evaluate
//NaN values as 0 for a loop.
for (i=0;i /*
 Check if we are in the last row so we can bail out.
 Without this check, if the user enters a number that would go beyond
 the last row the script would end up deleting backwards. That might
 be desirable, but seems counterintuitive to me. As written it allows
 you to “delete from here to end” without needing to know exactly how
 many rows you are deleting (just enter some big reasonably large value).
var rowsXPath = “ancestor-or-self::” + tableRowElem + “/following-sibling::” + tableRowElem;
var rowNodesAfter = rng.ContainerNode.getNodesByXPath(rowsXPath);
if (rowNodesAfter.length == 0) {
deletedTheLastRow = true;
if (deletedTheLastRow) {
//Turn formatter back on
ActiveDocument.FormattingUpdating = true;
//End the script
//Turn formatter back on (“just in case”).
//Thorough testing of the code above should allow this line to be removed.
//However, failure of any of the above might also mean the code never gets
//this far, leaving the formatter off, and requiring the file to be reopened.
ActiveDocument.FormattingUpdating = true;
else Application.Beep();
else Application.Beep();[/code]