I try to find out in which column of a table my grafic is placed. I like to adjust each column width depending on the grafic and document size.
The code example at the end of this post just displays my problem.
The script is:
- parsing through all grafics
- checking if FrameParent is FO_SubCol
- putting the FirstCell of the SubCol in an object
- calculates the new widths of the column (the example does not include the whole code)
- using the Cell.CellColNum to find the index (vcounter) for the column width in Tbl.TblColWidths
- setting the new TblColWidths
vcounter is always=0, although the grafic is in the second or third column
0 for column 1
1 for column 2
2 for column 3
Where is my misunderstandig of the SubCol, Cell objects?
var vGraphic =app.ActiveDoc.FirstGraphicInDoc;
vTextLocObj = new TextLoc (vGraphic.FrameParent , 0);
vColWidth=(130/vTbl.TblNumCols) * docobj.ViewDisplayUnits;
I got to messing around with this and I'm just as confused as you are. The FirstCell property appears to return a cell object, but it doesn't seem to be a valid object. None of the properties seem to work, including CellColNum. If you try the NextCell property to step across the columns, it continues to return additional cell objects that behave the same.
For example, here's some code I ran, where InTextObj is a subcolumn:
cell = tl.obj.InTextObj.FirstCell;
i = 0;
while(typeof(cell)!= "undefined" && i < 1000)
cell = cell.NextCellInRow;
...that loop runs straight to 1000
Sorry, I didn't finish that before clicking Post.
So, the object returned by FirstCell seems to be bogus. Furthermore, if you do this:
...you get zero, which implies a bogus object. Furthermore, I did this with the FDK:
cellId = F_ApiGetId(docId, subcolId, FP_FirstCell);
....and got a zero for the object handle.
So, I think that FirstCell is not what we think it is, or it is unreliable, or something. I think we need somebody to explain this property to us.
Sorry that I couldn't find the answer, but I wanted to at least report what I discovered.
It is interesting that this property appears valid with FrameScript. If I insert a table on the first page of a blank FrameMaker 10 document, and click in the paragraph containing the table anchor, I can run this:
Set oPgf = TextSelection.Begin.Object;
Set oSubCol = oPgf.InTextObj;
Set oCell = oSubCol.FirstCell;
oCell is a valid object; I can query its properties, display its text, etc. However, if the table has a title, the oCell object will actually be the "cell" containing the table title (which is strange).
I don't think the FirstCell property of the SubCol is what you want to use any way. Why not just start with the table object itself and navigate through the cells? Here is how it would be in FrameScript with the selected table, but you can adapt this to ExtendScript:
Set oDoc = ActiveDoc;
Set oTbl = oDoc.SelectedTbl;
Set oCell = oTbl.FirstRowInTbl.FirstCellInRow;
// See if the cell contains an anchored frame.
Get TextList InObject(oCell.FirstPgf) FrameAnchor NewVar(tTextList);
If tTextList.Count > 0
// Do something here.
Set oCell = oCell.NextCellInTbl;
Or, if you want to start with a graphic object, do something like this.
// Get the anchored frame containing the graphic.
Set oAFrame = oGraphic.FrameParent;
// See if the anchored frame is in table cell.
If oAFrame.TextLoc.InTextObj.ObjectName = 'Cell'
Set oCell = oAFrame.TextLoc.InTextObj;
// Do something here.
Hi Russ, Hi Rick,
thanks for your replies. A lot of strange things with this cell and SubCol object in ExtendScript.
I also recognize "if the table has a title, the oCell object will actually be the "cell" containing the table title".
Also if the graphic is in the second column, the oCell contains the table title of the first column.
Rick, regarding to your suggestions:
- if I navigate through the table cells, I have first to figure out, if there is a grafic in the cell to resize, then resize the grafic and then resize the column.
I like the grafic approach, because its shorter, but for this I have to know in which column the grafic is in.
- if I navigate to the grafics and get only the cell object (without the SubCol), I'll not know which column of the table I have to resize
I did it in Framesript and it works.
If vGraphic.ObjectName ='Inset'
Set vTextLocObj = vGraphic.FrameParent.TextLoc;
If vTextLocObj.InTextObj.ObjectName = 'Cell'
Set vTbl = vTextLocObj.InTextObj.CellTbl;
Set vTblWidth = vTbl.TblWidth;
vColWidth=(130/vTbl.TblNumCols) * ActiveDoc.ViewDisplayUnits);
Replace Member Number(vCounter) In(vWidths) With(vColWidth);
Set vGraphic =vGraphic.NextGraphicInDoc;
I'll try the find a solution with the "navigate through the table cells" approch. But it would be nice if there is a solution for the "navigate through the graphic approach")
bjoern (i tried to change my screen name in my profile, but it did not work)
If you want to iterate based on graphics, perhaps you might consider a different approach that doesn't involve the FirstCell property. I think that the CellColNum property is OK... it's the FirstCell property that isn't working or we just don't understand how it works.
Here is a little function I ran to verify that CellColNum does work OK, as long as the cell object is valid. I don't know if this methodology will work in your case, but perhaps it will give you some ideas.
var doc = app.ActiveDoc;
var graphic = doc.FirstGraphicInDoc;
//iterate through all the graphics in the doc
//for this test, we only care about imported files
if(graphic.type == Constants.FO_Inset)
//get the frame parent. If it's an anchored frame, then we want to
//find out if it's in a table cell or not.
var aframe = graphic.FrameParent;
if(aframe.type == Constants.FO_AFrame)
//get the InTextObj of the paragraph that contains the frame anchor
var subcol = aframe.TextLoc.obj.InTextObj;
//if it is a table cell, report the column
if(subcol.type == Constants.FO_Cell)
alert("Graphic '" + graphic.InsetFile + "' is in a table, column " + subcol.CellColNum);
//otherwise, just report
alert("Graphic '" + graphic.InsetFile + "' is not in a table");
graphic = graphic.NextGraphicInDoc;
thx. That's what I need.
I did not know, that InTextObj can directly point to the Cell object.
In the documentation is written:
"Indicates the column or text frame in which the anchored frame is written."
This was the reason why I used the FirstCell property, because I thought it can only be a SubCol.
Russ and Rick, thanks a lot for your help.
For future reference, table cells seem to be some kind of individual text frames within FM, at least as far as internal processing. They behave like text frames, in that movement between them is clunky, they cannot break across pages, etc. So, from a scripting perspective, I think it's common for a property to return a cell object even when you are expecting a text frame, because that's apparently how the table model behaves. Note that much of this is speculation... I didn't write the FM code
The documentation is clearly wrong on this: InTextObj does not return a TextFrame object; that is the purpose if the InTextFrame property. It is wrong in the FDK Programmer's Reference, which is probably where the ExtendScript docunentation is derived from. The description for InTextObj is correct under the Pgf object in both ExtendScript and FDK docs:
Subcolumn, footnote, or table cell the paragraph begins in (SubCol, Fn, or Cell).