Skip to main content
1-Visitor
August 4, 2010
Question

table sort

  • August 4, 2010
  • 5 replies
  • 1330 views
I just got stumped. A user wants to sort a table by column. I have no clue
if that is possible. I am using version 5.2. Our data is SGML.

d

    5 replies

    18-Opal
    August 4, 2010
    Hi Doug-



    It's not there out of the box, but I know it can be done. A while back a
    few of us tried our hand at different approaches, and found several that
    worked. Someone did one that was pure ACL, another person did one based
    on XSLT, and IIRC I did one that was all AOM. Unfortunately I can't find
    those files any more, so I can't post a sample. But here's the basic
    approach I'd take from an AOM perspective:



    1) Write a function that can sort a table based on values in a
    particular column, given that the cursor is in a table header cell for
    that column

    2) Use an event listener to capture a double-click on a table row
    header that triggers the function you wrote in step 1.

    3) OR, alternatively, add an entry to the editor window context
    menu to let them sort by right-clicking a table cell header.



    --Clay


    18-Opal
    August 4, 2010
    Hi Doug-



    I did manage to dig up an early version of the code. This one requires
    you to select the table and then invoke the sort function (which you
    could do from a command line or from a custom menu item, etc.). It's
    pretty basic, there are a number of ways you could spruce it up. The UI
    in particular is very bare bones; it basically presents you with a list
    of the entries in the first row of the table and wants you to give it a
    number corresponding to the column on which you want to sort. But
    hopefully it will get you started.



    --Clay



    // ---------------- pasted code -----------------//



    // type="text/jscript"



    // adds ability to sort a table

    // version 0.1 is fairly rudimentary, it will get confused by spanned
    cells and other

    // such complexities, it is meant strictly for a straightforward
    rectangular table where

    // all rows have the same number of cells



    var tableSortColumnIndex;



    function sortTable() {

    TABLE_TYPE = 2;

    doc = Application.activeDocument;

    // if selection is not a table or part of one, abort

    if (doc.selectionType != TABLE_TYPE) {

    Application.alert("Table must be selected before it can be sorted");

    return;

    }

    // get the current table

    selection = doc.tableSelection;

    trect = selection.rectangle(1);

    // get array of column headings for prompt

    headings = new Array();

    for (i=0;i < trect.width;i++) {

    headings.push(trect.cells.item(i).column.topCell.contents.toString()
    + " (" + (i+1) + ")");

    }

    // prompt user

    sortcol = promptTableSort(headings);

    // check user selection to make sure it's feasible

    if (canSort(trect,sortcol)) {

    // stuff table rows in an array so we can sort them

    tableSortColumnIndex = sortcol;

    rows = new Array();

    firstrow = trect.upperLeft.row.index;

    for (i=0;(rowcell = trect.cellsOnLeftEdge.item(i));i++) {

    rows.push(rowcell.row);

    }

    // sort rows in the array

    rows.sort(compareRows);

    // insert sorted rows after selection

    tgrid = trect.upperLeft.grid;

    targetrow = trect.lowerLeft.row;

    for (i=0; (row = rows[i]); i++) {

    // skip if source row is a header row

    if (row.getAttribute("header_level")=="0") {

    targetrow = tgrid.addRow(targetrow);

    for (j=1; j <= row.cellCount; j++) {


    targetrow.cell(j).contents.insertNode(row.cell(j).contents.extractConten
    ts());

    }

    }

    }

    // now delete the originals (except for header rows)

    for (i=0; (row = rows[i]); i++) {

    if (row.getAttribute("header_level")=="0") {

    tgrid.deleteRow(row);

    }

    }



    }

    else {

    // give error

    Application.alert("Invalid sort column, select a number from 1 to "
    + trect.width + ".");

    }

    }



    function promptTableSort(headings) {

    // need to polish this!

    response = Application.prompt(headings.join(","),"1");

    if (response==null) return null;

    else return parseInt(response);

    }



    function canSort(rect,sortcol) {

    if (sortcol == null) return false;

    if (sortcol <= rect.width) return true;

    else return false;

    }



    function compareRows(a,b) {

    if (a.cell(tableSortColumnIndex).contents.toString().toLowerCase() <
    b.cell(tableSortColumnIndex).contents.toString().toLowerCase()) return
    -1;

    else if
    (a.cell(tableSortColumnIndex).contents.toString().toLowerCase() >
    b.cell(tableSortColumnIndex).contents.toString().toLowerCase()) return
    1;

    else return 0;

    }




    1-Visitor
    August 4, 2010
    Here is an ACL-only, sorts on first column only, table sort package. I think
    it is at least based on, if not totally lifted from, the experiment Clay
    mentioned.

    package table_sort

    function table_sort() {
    if (oid_xpath_boolean(oid_caret(),'ancestor::tbody')) {
    local chgtrk = option("changetracking")
    set changetracking = off;

    while (oid_name(oid_parent(oid_caret())) != 'tbody') {
    goto_oid(oid_parent(oid_caret()));
    }
    goto_oid(oid_parent(oid_caret()));

    if (oid_find_child_attrs(oid_caret(), morerowsarr, 'morerows')) {
    response('Tables with vertical spans can not be sorted.');
    set changetracking = $chgtrk;
    return;
    } # if


    rows = oid_find_children(oid_caret(), rowarr, "row");

    if ($rows > 0) {
    for (i = 1; i <= $rows; i++) {
    if (store_rows_arr[oid_content(oid_child($rowarr[$i],1))] == '') {
    store_rows_arr[oid_content(oid_child($rowarr[$i],1))] =
    oid_content($rowarr[$i],0x1);
    sort_rows_arr[$i] = oid_content(oid_child($rowarr[$i],1));
    } # if
    else {
    tempkey = oid_content(oid_child($rowarr[$i],1)) . $i;
    store_rows_arr[$tempkey] = oid_content($rowarr[$i],0x1);
    sort_rows_arr[$i] = $tempkey;
    } # else
    } # for

    qsort(sort_rows_arr);

    for (i = 1; i <= count($sort_rows_arr); i++) {
    insert(store_rows_arr[$sort_rows_arr[$i]]);
    }

    for (i = 1; i <= $rows; i++) {
    oid_delete($rowarr[$i]);
    } # for
    message "$rows rows sorted.";
    beep;
    } # if
    else {
    response('No rows found to sort. Interesting. Let your administrator
    know.');
    }

    delete(store_rows_arr);
    delete(sort_rows_arr);
    set changetracking = $chgtrk;
    } # if
    else {
    response('Place your cursor in the body (tbody) of the table or
    informaltable to be sorted before attempting to Sort Table.');
    } # else

    } # table_sort
    1-Visitor
    August 5, 2010
    This is for the record. I don't know if it is practical.

    FOSI indexing performs sorting. Help 70-1 describes sorting a FOSI-generated
    table. Help 1239 describes how to rename preliminary and final index markup. It
    seem to me it should be possible to rename preliminary index markup to the
    appropriate table markup. I'm thinking a system-func in the FOSI could call ACL
    to determine and return to the FOSI the number of the column with the cursor.

    With this approach, print/PDF output should be straightforward, but there would
    be two tables in the Edit window, the unsorted input table and the sorted output
    gentable. Only the input table could be edited. I'm not certain, but I think the
    output gentable would automatically update/re-sort when the input table was
    edited. If not, update gentext would be needed to show the changes in the output
    table.

    Standard disclaimer: I have not tried this. If it works, please share!

    Good luck!

    Suzanne Napoleon
    www.FOSIexpert.com
    "WYSIWYG is last-century technology!"


    1-Visitor
    August 7, 2010
    Thanks to all:

    I am using the ACL version. The only issue is the qsort works with column
    one. So the user must move the column to the first position and run the
    sort. Then move it back to the real position. That is all good, it is not
    that often we need to do this.

    d


    On Wed, Aug 4, 2010 at 8:37 PM, Suzanne Napoleon <
    SuzanneNapoleon@fosiexpert.com> wrote:

    > This is for the record. I don't know if it is practical.
    >
    > FOSI indexing performs sorting. Help 70-1 describes sorting a
    > FOSI-generated table. Help 1239 describes how to rename preliminary and
    > final index markup. It seem to me it should be possible to rename
    > preliminary index markup to the appropriate table markup. I'm thinking a
    > system-func in the FOSI could call ACL to determine and return to the FOSI
    > the number of the column with the cursor.
    >
    > With this approach, print/PDF output should be straightforward, but there
    > would be two tables in the Edit window, the unsorted input table and the
    > sorted output gentable. Only the input table could be edited. I'm not
    > certain, but I think the output gentable would automatically update/re-sort
    > when the input table was edited. If not, update gentext would be needed to
    > show the changes in the output table.
    >
    > Standard disclaimer: I have not tried this. If it works, please share!
    >
    > Good luck!
    >
    > Suzanne Napoleon
    > www.FOSIexpert.com
    > "WYSIWYG is last-century technology!"
    >