0

I have added table in InDesign document and populated data within the same using javascript. But at one place I would need to display horizontal bar graph depending upon the percentage in table cell. The Below image is how required output should be? Required Output

The below image is what I have populated The table which I have populated

Anybody please let me know how that can be done? Below is my code for doing so.

    main();

    function main(){

        var inputBuild = "/C/Test/xml/A";
        var inputIndt = "/C/Test/indt/B"; 
        // Read indt file object.
        var curFile = File (inputIndt+"/Draft.indt");  
        // check if the file exists  
        if (!curFile.exists) {  
            alert ( "no template!" );  
            exit();  
        }  
        // open the file  
        var curDoc = app.open( curFile );  

        // Reading xml file file 
        xmlFile = new File(inputBuild+"/Build.xml"); 
        if (!xmlFile.exists) exit();      

        xmlFile.open("r");   
        xmlStr = xmlFile.read(); 
        xmlFile.close();  
        root = new XML(xmlStr);

        // Get text frames start
        var curLayer = curDoc.layers[0];

        tfTableFP = curLayer.textFrames.item("Tab_Fund_Position");

        loadDataToTables(root, curLayer, '');

    }

    function loadDataToTables(root, curLayer, reportId){

        var fundPosTable = tfTableFP.tables[0];

        loadDataToFundPosition(root,fundPosTable);
    }

    function loadDataToFundPosition(root,tblName){
        var fundPositionList = root.xpath("/Component/FundPositions/TableData/Item");
        var rowCount = fundPositionList.length();

        if(rowCount != 0){  

            tblName.bodyRowCount = rowCount;

            for(counter = 0; counter < tblName.rows.length; counter++){

                if (counter == 0 || counter == 1){

                }else{
                tblRow = tblName.rows.item(counter);

                component = fundPositionList[counter-2];

                for(cellCounter = 0; cellCounter < tblRow.cells.length; cellCounter++){
                    if(cellCounter == 0){
                        tblString =  component.AssetGroup;
                        tblRow.cells.item(cellCounter).contents =  tblString.toString();
                    }else if(cellCounter == 1){
/*Progress bar/bar graph for negative data to be populated in this cell*/
                        tblString =  component.NetMarketExposure;
                        tblRow.cells.item(cellCounter).contents = tblString.toString();
                    }else if(cellCounter == 2){
/*Progress bar/bar graph for positive data to be populated in this cell*/
                        tblString =  component.StrategicAllocation;
                        tblRow.cells.item(cellCounter).contents = tblString.toString();
                    }else if(cellCounter == 3){
                        tblString =  component.FlexibleOverlay;
                        tblRow.cells.item(cellCounter).contents = tblString.toString();
                    }else if(cellCounter == 4){
                        tblString =  component.NetRange;
                        tblRow.cells.item(cellCounter).contents = tblString.toString();
                    }

                }
                }
            }
        }
    }

Build.xml

<?xml version="1.0" encoding="UTF-8" ?>
<Component ID="645248" asmid="1" def="Sheet" type="Document">
<FundPositions>
<TableData>
<Item>
<RowRank>9</RowRank>
<Port_ID>201</Port_ID>
<RowType>asset_group total</RowType>
<AssetGroup>Test1</AssetGroup>
<AssetDetail>N/A</AssetDetail>
<ActiveSecurity>28.38%</ActiveSecurity>
<DerivativeOverlay>-13.34%</DerivativeOverlay>
<NetMarketExposure>15.04%</NetMarketExposure>
<StrategicAllocation>35%</StrategicAllocation>
<FlexibleOverlay>+/- 35%</FlexibleOverlay>
<NetRange>0% to 70%</NetRange>
</Item>
<Item>
<RowRank>9</RowRank>
<Port_ID>201</Port_ID>
<RowType>asset_group total</RowType>
<AssetGroup>Test2</AssetGroup>
<AssetDetail>N/A</AssetDetail>
<ActiveSecurity>29.17%</ActiveSecurity>
<DerivativeOverlay>-1.36%</DerivativeOverlay>
<NetMarketExposure>27.80%</NetMarketExposure>
<StrategicAllocation>30%</StrategicAllocation>
<FlexibleOverlay>+/- 30%</FlexibleOverlay>
<NetRange>0% to 60%</NetRange>
</Item>
<Item>
<RowRank>2</RowRank>
<Port_ID>201</Port_ID>
<RowType>asset_group total</RowType>
<AssetGroup>Test3</AssetGroup>
<AssetDetail>N/A</AssetDetail>
<ActiveSecurity>14.72%</ActiveSecurity>
<DerivativeOverlay>0.00%</DerivativeOverlay>
<NetMarketExposure>14.72%</NetMarketExposure>
<StrategicAllocation>15%</StrategicAllocation>
<FlexibleOverlay>+/- 20%</FlexibleOverlay>
<NetRange>-5% to 35%</NetRange>
</Item>
<Item>
<RowRank>2</RowRank>
<Port_ID>201</Port_ID>
<RowType>asset_group total</RowType>
<AssetGroup>Test4</AssetGroup>
<AssetDetail>N/A</AssetDetail>
<ActiveSecurity>17.15%</ActiveSecurity>
<DerivativeOverlay>0.00%</DerivativeOverlay>
<NetMarketExposure>17.15%</NetMarketExposure>
<StrategicAllocation>15%</StrategicAllocation>
<FlexibleOverlay>+/- 20%</FlexibleOverlay>
<NetRange>-5% to 35%</NetRange>
</Item>
<Item>
<RowRank>3</RowRank>
<Port_ID>201</Port_ID>
<RowType>asset_group total</RowType>
<AssetGroup>Test5</AssetGroup>
<AssetDetail>N/A</AssetDetail>
<ActiveSecurity>5.34%</ActiveSecurity>
<DerivativeOverlay>0.00%</DerivativeOverlay>
<NetMarketExposure>5.34%</NetMarketExposure>
<StrategicAllocation>5%</StrategicAllocation>
<FlexibleOverlay>+/- 15%</FlexibleOverlay>
<NetRange>-10% to 20%</NetRange>
</Item>
<Item>
<RowRank>1</RowRank>
<Port_ID>201</Port_ID>
<RowType>detail</RowType>
<AssetGroup>Test6</AssetGroup>
<AssetDetail>Cash &amp; Cash Equivalents</AssetDetail>
<ActiveSecurity>18.24%</ActiveSecurity>
<DerivativeOverlay>0.91%</DerivativeOverlay>
<NetMarketExposure>19.15%</NetMarketExposure>
<StrategicAllocation>N/A</StrategicAllocation>
<FlexibleOverlay>N/A</FlexibleOverlay>
<NetRange>N/A</NetRange>
</Item>
<Item>
<RowRank>2</RowRank>
<Port_ID>201</Port_ID>
<RowType>asset_group total</RowType>
<AssetGroup>Test7</AssetGroup>
<AssetDetail>N/A</AssetDetail>
<ActiveSecurity>-16.25%</ActiveSecurity>
<DerivativeOverlay>17.06%</DerivativeOverlay>
<NetMarketExposure>0.80%</NetMarketExposure>
<StrategicAllocation>N/A</StrategicAllocation>
<FlexibleOverlay>N/A</FlexibleOverlay>
<NetRange>N/A</NetRange>
</Item>
</TableData>
<FundPositions_Summary>Net Market exposure summary</FundPositions_Summary>
<FundPositions_Total>100.00%</FundPositions_Total>
</FundPositions>
</Component>
yatinbc
  • 605
  • 3
  • 16
  • 37

2 Answers2

0

Given that percentages are written under the form -xx%, -xx.xx%, xx%, xx.xx% and that your doc counts two object styles named red and green, here is an approach:

var main = function() {
 var doc = app.properties.activeDocument;
 if ( !doc ) return;
 
    var green = doc.objectStyles.itemByName ( "green");
    var red = doc.objectStyles.itemByName ( "red");
    
    if ( !green.isValid || !red.isValid ) {
        alert("A green a/o red object styles is(are) missing. Please create those and run again.");
        return;
    }
    
 var fgp = app.findGrepPreferences.properties;
 app.findGrepPreferences = null;
 
 app.findGrepPreferences.properties = {
  findWhat : "^-?\\d+(\\.\\d+)? ?%$",
 }
 
 var found = doc.findGrep();
 var n = found.length;
 
 if( !n ) {
  alert("sorry no % values found");
  return;
 }
    
    
    
    
 var para, isPositive, pCell, cellWidth, cellHeight,
        bottom, left, right, top, pct, rectWidth;
 var max = 150;
 
 while ( n--) {
  para = found[n];
        pCell = para.parent;
        
  if (pCell instanceof Cell ) {
            
   isPositive = para.contents[0]!="-";
   
            cellWidth = pCell.width;
             cellHeight = pCell.height;
            bottom = pCell.bottomInset;
            left = pCell.leftInset;
            right = pCell.rightInset;
            top = pCell.topInset;
            
            cellWidth = (cellWidth-left-right)*.75; 
            textWidth = (para.endHorizontalOffset - para.horizontalOffset)*1.1;
            pct = Number( para.contents.replace(/[\-%]/g, "") );
            
            rectWidth = (cellWidth*pct)/max;
            
            para.insertionPoints[isPositive? 0 : -1 ].rectangles.add( {
                geometricBounds:[0, 0, cellHeight-top-bottom, rectWidth],
            }).appliedObjectStyle = (isPositive? green : red ),
            
             para.insertionPoints[isPositive? 1 : -1 ].contents = " ";
   
  }
  
 }
 
 
 app.findGrepPreferences.properties = fgp;
}

var u;

app.doScript ( "main()",u,u,UndoModes.ENTIRE_SCRIPT, "The Script" );

enter image description here

Loic
  • 2,173
  • 10
  • 13
  • Hi I have added my code for populating data in table where I am finding difficulties while integrating the same with your solution. – yatinbc Jan 18 '17 at 07:36
  • Your code seems more complicated than it should but it's hard to offer more help without a clear xml structure understanding and what you intend to achieve exactly. – Loic Jan 18 '17 at 10:20
  • I have added my xml in edited post. I want to get those bar graph/progress bar in table cell corresponding to number of %tage populated to cell – yatinbc Jan 18 '17 at 12:27
  • Hey Loic, I've done it by merging both the codes(My code and your solution for drawing progress bar/bar graph ) I got green and red bar in table cell. But now problem is I want to align the text within table cell to right or left. I ftext getting populated to table cell then it should get aligned to right and if text getting populated to cell is positive then it should get aligned to left. – yatinbc Jan 19 '17 at 14:42
  • And other thing is here it is scanning entire active document of for %tage sign if we want to scan only particular table data for %tage sign then how to do that? – yatinbc Jan 19 '17 at 14:50
  • It's wide open. You can force user to select a table and find/grep % on that selection. You can look for tables with a specific label… – Loic Jan 20 '17 at 13:33
0

Ok so you can use this snippet to populate the table then run teh previous script for bars. However most of the values will fail as they are not covered by the grep expression. Will let you work on that part.

var baseUrl = Folder.desktop+"/xml";
//replace by /C/Test/xml on your side

var main = function() {
 var doc,
 tf, tb;
 
 var inputBuild = baseUrl+"/A";
     var inputIndt =baseUrl+"/B"; 
  
  var build = File ( inputBuild+"/Build.xml" );
  var template = File ( inputIndt+"/Draft.indt" );
  
  if ( !build.exists || !template.exists ) {
  alert ( "a file is missing" );
  return;
 }

 doc = app.open ( template );
 tf = doc.layers[0].textFrames.itemByName ( "Tab_Fund_Position" );
 if ( !tf.isValid ) {
  alert( "Couldn't locate Tab_Fund_Position text frame on layer 1" );
  return;
 }

 tb = tf.parentStory.tables[0];
 
 if ( !tb.isValid ) {
  alert( "Couldn't locate a table in Tab_Fund_Position text frame" );
  return;
 }
 
 try {
  populateTable ( tb, build );
 }
 catch(err) {
  alert( err.line+"//"+err.message );
 }
}

function populateTable ( table, xmlFile ) {
  var x = getXML(xmlFile); 
  var items = x..Item, n = items.length(), i = 0, content = [], item, u = "",
  nme, sal, fxo, nrg;  
  if ( !n ) {
   throw new Error ( "No data found in XML" );
  }
 
  table.bodyRowCount = n*5;
  table.columnCount = 3;
 
  while (i<n ) {
   item = items[i];
   nme = String(item.NetMarketExposure);
   sal = String(item.StrategicAllocation);
   fxo = String(item.FlexibleOverlay);
   nrg = String(item.NetRange);
   content = content.
    concat ( 
     [String(item.AssetGroup),u,u]
    ).
    concat (
     ["NetMarketExposure"]
    ).
    concat (
     nme[0]=="-"? [nme, u ] : [u, nme ]
    ).
    concat (
     ["StrategicAllocation"]
    ).
    concat (
     sal[0]=="-"? [sal, u ] : [u, sal]
    ).
    concat ( 
     ["FlexibleOverlay"]
    ).
    concat (
     fxo[0]=="-"? [fxo, u ] : [u, fxo]
    ).
    concat ( 
     ["NetRange"]
    ).
    concat (
     nrg[0]=="-"? [nrg, u ] : [u, nrg]
    );
   i++;
  }
 
 
  table.contents = content;
}

function getXML( xmlFile ) {
 var  c, x;
 xmlFile.encoding = "UTF-8";
 xmlFile.open('r');
 c = xmlFile.read();
 xmlFile.close();
 return XML( c );
}

var u;

app.doScript ( "main()",u,u,UndoModes.ENTIRE_SCRIPT, "The Script" );
Loic
  • 2,173
  • 10
  • 13
  • I am not getting. Will the above line of code is enough for solution or I need to merge with below code. When I tried to execute the below code two alerts in code got popped up. how to create those styles and how to get findGrep and length for the same. – yatinbc Jan 18 '17 at 14:08
  • hey! Please exlpain – yatinbc Jan 19 '17 at 12:10
  • No you need to merge both code. The second one takes care of populating data when the first one deals with adding the bars. One could merge both but it was too much effort for me in my timeframe. Sorry about that. – Loic Jan 19 '17 at 13:57
  • Hey Loic, I've done it by merging both the codes(My code and your solution for drawing progress bar/bar graph ) I got green and red bar in table cell. And other thing is here it is scanning entire active document of for %tage sign if we want to scan only particular table data for %tage sign then how to do that? – yatinbc Jan 20 '17 at 06:25
  • But could you please help me at one more place? I want to draw that progress bar only at specific places not within entire document. How can we scan particular table cell only to draw that bar graph? Because what happening that now the grep which we have defined scanning entire active document for %tage sign and then loop through those many time and draw that bar graph depending upon isPositive flag. – yatinbc Jan 20 '17 at 09:21