Copy link to clipboard
Copied
Hello,
I am structuring a document using a conversion table. I want to be able to apply a specific paragraph format to those paragraph format names that do not appear in the conversion table. I am having difficulty getting text from the cellIds in the Conversion table. All I get are the format names in the paragraph catalog. Maybe I am missing something here...I would appreciate any inputs.
Am pasting some code, where I've gotten so far...Questions pertaining to this issue are in the comments inline.
//Get docId, flowId, textFrameId and pgfId here...
//Open Conversion Table document here...ID is "convTabId"
F_TextRangeT ctr;
F_PropValsT props;
while(pgfId) {
//Traverse through paragraphs in the current document (docId) and get their format names.
pgfName = F_ApiGetString(docId, pgfId, FP_Name);
if(!pgfName) return;
//Check if this pgfName is in the conversion table's first column..RICI, R2C1,R3C1...
retVal = IsInConvTable(convTabId,pgfName);
//retVal contains 1 if pgfName is in Conversion table, 0 otherwise..
if(!retVal) {
//Apply "Body" format to this paragraph.
bodyFmtId = F_ApiGetNamedObject(docId,FO_PgfFmt,"Body");
if(!bodyFmtId) return;
props = F_ApiGetProps(docId,bodyFmtId);
if(props.len == 0) return;
ctr.beg.objId = ctr.end.objId = pgfId;
ctr.beg.offset = 0;
ctr.end.offset = FV_OBJ_END_OFFSET;
F_ApiSetTextRange(FV_SessionId, docId, FP_TextSelection, &ctr);
F_ApiSetProps(docId,ctr.beg.objId,&props);
}
pgfId = F_ApiGetId(docId,pgfId,FP_NextPgfInFlow);
}
int IsInConvTable(F_ObjHandleT convTabId, ConStringT paraName)
{
//declare tblId, rowId, cellId, paraId;
F_TextItemsT textItems;
IntT retVal=0, i;
F_TextRangeT tr;
//Get Table and Row Ids
tblId = F_ApiGetId(FV_SessionId, convTabId, FP_FirstTblInDoc);
rowId = F_ApiGetId(convTabId, tblId, FP_FirstRowInTbl);
while(rowId) {
//Get Cell Ids of only the first column in each row of the Conversion table.
cellId = F_ApiGetId(convTabId, rowId,FP_FirstCellInRow);
paraId = F_ApiGetId(convTabId, cellId, FP_FirstPgf);
tr.beg.objId = tr.end.objId = paraId;
tr.beg.offset = 0;
tr.end.offset = FV_OBJ_END_OFFSET;
F_ApiSetTextRange(FV_SessionId, convTabId,FP_TextSelection,&tr);
textItems = F_ApiGetTextForRange(convTabId,&tr,FTI_String);
//Here textItems contains names in Paragraph Catalog, such as, P:Body, P:Heading1...
//I require the entries in the conversion table and not those in the Paragraph catalog...
//This happens if the following command is used too:
//textItems = F_ApiGetText(convtabId,cellId,FTI_String);
if (textItems.len != 0)
//How do we cast textItems values to ConStringT, for the following substring operation?
i = F_StrSubString(textItems,paraName);
if ( != -1)
retVal=1;
F_ApiDeallocateTextItems(&textItems);
rowId = F_ApiGetId(convTabId, rowId, FP_NextRowInTbl);
}
return retVal;
}
Many thanks,
pnk
Copy link to clipboard
Copied
//Get Table and Row Ids
tblId = F_ApiGetId(FV_SessionId, convTabId, FP_FirstTblInDoc);
pnk,
to me the whole thing looks very complicated, but I guess that’s how C works and I am just a FrameScript user. I can not help you with type casting, though...
Anyway, regarding the quoted line, how can you be sure that your table is the "first table in document"? In many cases it isn’t, what you most probably want is the first table in the main flow of the document, or maybe a table with a certain table format name.
And also: You did not tell us what you really want to achieve, maybe all this can be avoided by cleverly using built-in features of the product. It seems to me you want to highlight paragraphs which will not be handled by a conversion table (for going to structured?). If this is the case, assigning another paragraph format will remove any information of the paragraph.
- Michael
Copy link to clipboard
Copied
Hi Michael,
Thanks for your reply. I should have given an overview of what I am trying to achieve.
I have an unstructured document, with numerous paragraphs, each having different formats. I want to convert this document to a structured one. However, I do not want to define all the paragraph format names(most of them not-so-relevant) in my Conversion table. So I only define the most important paragraph format names in the Conversion table.
The idea is to format all the other (not-so-relevant) different paragraph format names, with a single pgf format name, say for example, "Body" - so that I can define only P:Body in my conversion table and wrap it up in an element. Perhaps there are other methods, this was just an idea..
In the code, first I open the document containing the conversion table. This document contains only one table - i.e, the conversion table. Thats the reason for using FP_FirstTblInDoc property.
//Get Table and Row Ids
tblId = F_ApiGetId(FV_SessionId, convTabId, FP_FirstTblInDoc);
The algorithm goes like:
Hope this helps..
I found a solution for casting "textItems", though I don't know if its the correct way.
declare a char array;
char *dbmsg;
for(k=0;k<textItems.len;k++){
F_Sprintf(dbmsg,textItems.val
}
Now, dbmsg holds the value in the textItems. This can be used in the F_SubStr function.
Many thanks,
pnk
Copy link to clipboard
Copied
Hi pnk,
Michael has made an astute observation about your method of retrieving the table. There are likely many tables in the doc (esp. on the reference pages) and it is unpredictable which one will be returned as the first. If you have managed to get the right one so far, I think you may have been lucky. I would consider writing a separate function for this that has contingencies to iterate through all the tables in the doc, either checking the heading text or table format to determine if you've gotten the right one.
Having said that, your text implies that you have managed to get the right table. For getting a string from a F_TextItemsT structure, it is very simple. You don't need to cast it... StringTs are already members of the structure. For example:
i = F_StrSubString(textItems.val[0].u.sdata, paraName);
...should work find. There are some caveats to this example, though:
- For this to work in your code, there must be nothing else in the text of the cell except the P:etc. declaration. Anything else, such as line breaks, markers, whatever, will break up the string into multiple sdata members.
- You will want to keep that check that you currently have to make sure the structure isn't empty. An empty structure will invite a crash. For example:
if(textItems.len > -1)
i = F_StrSubString(textItems.val[0].u.sdata, paraName);
else
i = -1;
There are some other areas of your code that are a bit questionable, some that are more serious than others. One example:
if(!pgfName) return;
If your paragraph ID is valid, this should never return a null pointer. If you are attempting to check if the string is empty, use F_StrEqual() or F_StrCmp() instead.
Also:
props = F_ApiGetProps(docId,bodyFmtId);
if(props.len == 0) return;
There are a number of problems here. First of all, you don't deallocate props anywhere, so this will become a major memory leak. You have to deallocate these structures whenever you are done with them (F_ApiDeallocatePropVals() ). Secondly, the abrupt return in the event of a failure is generally considered suboptimal. Here is an idea... make this call at the very beginning of the function and just reuse props in the while loop. There is no need to populate props every time you want to apply a format to a paragraph... it is the same data every time. Even if you were deallocating properly, you would be forcing a lot of unnecessary processing (read "expensive");
Also, this part is convoluted:
ctr.beg.objId = ctr.end.objId = pgfId;
ctr.beg.offset = 0;
ctr.end.offset = FV_OBJ_END_OFFSET;
F_ApiSetTextRange(FV_SessionId, docId, FP_TextSelection, &ctr);
F_ApiSetProps(docId,ctr.beg.objId,&props);
...all you should need is:
F_ApiSetProps(docId, pgfId, &props);
By forcing a text selection every time, you will really slow down the process.
Also, you haven't deallocated the paragraph name which is another memory leak.
Also, your method of getting the text from the cell paragraph is convoluted.
Also, you could save some more time by breaking out of IsInConvTable() as soon as a match is found. You should do this since you are forcing this process with every paragraph in the main doc.
Also, you haven't made any provisions for cases where one paragraph name is contained in another, possibly returning a false positive. This would take some more string handywork.
So with all that, I've reposted your code with some suggestions. I didn't test any of this so I might have syntax errors, but I think the general ideas will make your code considerably more reliable and robust. I hope this helps some. I don't mean to sound like I'm bashing your code... I think this is good stuff... just want to help out ![]()
Russ
F_PropValsT props;
. . .
props = F_ApiGetProps(docId,bodyFmtId);
if(props.len == 0) return;
. . .
while(pgfId) {
//Traverse through paragraphs in the current document (docId) and get their format names.
pgfName = F_ApiGetString(docId, pgfId, FP_Name);
if(F_StrCmp(pgfName, "") == 0)
{
F_ApiDeallocateString(&pgfName);
pgfId = F_ApiGetId(docId, pgfId, FP_NextPgfInFlow);
continue;
}
//Check if this pgfName is in the conversion table's first column..RICI, R2C1,R3C1...
retVal = IsInConvTable(convTabId, pgfName);
//retVal contains 1 if pgfName is in Conversion table, 0 otherwise..
if(!retVal)
F_ApiSetProps(docId, pgfId, &props);
F_ApiDeallocateString(&pgfName);
pgfId = F_ApiGetId(docId, pgfId, FP_NextPgfInFlow);
}
F_ApiDeallocatePropVals(&props);
}
int IsInConvTable(F_ObjHandleT convTabId, ConStringT paraName)
{
//declare tblId, rowId, cellId, paraId;
F_TextItemsT textItems;
IntT retVal=0, i;
//Get Table and Row Ids
tblId = F_ApiGetId(FV_SessionId, convTabId, FP_FirstTblInDoc);
rowId = F_ApiGetId(convTabId, tblId, FP_FirstRowInTbl);
while(rowId) {
//Get Cell Ids of only the first column in each row of the Conversion table.
cellId = F_ApiGetId(convTabId, rowId,FP_FirstCellInRow);
paraId = F_ApiGetId(convTabId, cellId, FP_FirstPgf);
textItems = F_ApiGetText(convTabId, paraId, FTI_String);
if (textItems.len != 0)
i = F_StrSubString(textItems[0].u.sdata, paraName);
else i = -1;
F_ApiDeallocateTextItems(&textItems);
if (i > -1)
{
retVal=1;
break;
}
rowId = F_ApiGetId(convTabId, rowId, FP_NextRowInTbl);
}
return retVal;
}
Copy link to clipboard
Copied
Copy link to clipboard
Copied
Are you trying to preprocess the document before applying the conversion table? That may not be necessary. Your conversion table can use P: with no paragraph tag following the colon to refer to any paragraph format that is not explicitly named in the conversion table. Thus, there is no need to map all such paragraph formats to a catch-all format before using the conversion table.
--Lynne
Copy link to clipboard
Copied
Am 24.04.2010 um 01:53 schrieb Lynne Price:
Are you trying to preprocess the document before applying the conversion table? That may not be necessary. Your conversion table can use P: with no paragraph tag following the colon to refer to any paragraph format that is not explicitly named in the conversion table. Thus, there is no need to map all such paragraph formats to a catch-all format before using the conversion table.
Lynne, what a great tip! Thanks a million,
- Michael
Copy link to clipboard
Copied
Hello,
Thanks much for your valuable inputs! Issue is resolved.
Thank you Michael for pointing out the probable error to me in the first place and Russ for explaining it in detail. The issue was of course with selecting the right table. While doing a table traversal, matching the header of each table, I found the following different tables, before the Conversion table:
All worked fine, when the right table was selected. Russ, thank you so much for your feedback, the detailed explanation and your time. I learned several new things from your post, including the best practices while coding. It was really helpful 🙂
And Lynne, thank you very much for the wonderful tip. In one word, "brilliant". Yes, all I was trying to do, was preprocess the document before applying the conversion table. I never imagined it to be this simple!
Thanks again,
pnk
Get ready! An upgraded Adobe Community experience is coming in January.
Learn more