Monday, June 7, 2010

Report generation in adobe director..

Report generation is perhaps the most plagued problem with director. There are a lot of xtras out there, but are commercial. Most of them are around $100-350, and all are limited in one way or another. After weeks of exploration, few of which included:
  1. Using adobe reader
  2. Interfacing it via. java program (this one almost worked)
  3. Wasted time with lots of useless xtras
I decided to make my own scheme, one which works in most situations. The idea is as follows:
  1. Create a HTML template of your report. For instance, if you wanted customer information report. You create a HTML template, fill in all the blanks with $1, $2, ... $n.
  2. From director, while generating the report, you first read in the template (preferably from root folder\templates\).
  3. Replace $1, $2, with appropriate values.
  4. Generate HTML file and open it with default browser.
I created a utility class for the above tasks. You'll be needing FileIO xtra and FileXtra4 (both of which are available for free)

-------------------------------------------------------------
--------------Report generation Utility class----------------
-------------------------------------------------------------

--Finds and replaces the first occurrence of 'aLookForString' with 'aReplaceString'
--in 'aString' and returns the new string
on findAndReplace me, aString, aLookForString, aReplaceString

n = aLookForString.length -1
is_ok = false

repeat while is_ok = false

place = offset(aLookForString, aString)

if (place = 0) then
is_ok = true
exit repeat
else
put aReplaceString into char place to (place+n) of aString
exit repeat
end if

end repeat

return aString
end

--Saves the text in given filename
on saveText me, text, filename

-- create the FileIO instance
fileObj = new(xtra "FileIO")

-- delete existing file, if any
openFile (fileObj,filename,2)
delete(fileObj)

-- create and open the file
createFile(fileObj,filename)
openFile(fileObj,filename,2)

-- check to see if file opened ok
if status(fileObj) <> 0 then
err = error(fileObj,status(fileObj))
alert "Error:"&&err
return FALSE
end if

-- write the file
writeString(fileObj,text)

-- close the file
closeFile(fileObj)

return TRUE

end

--Reads the text from a given filename
on readFromFile me, filename

-- create the FileIO instance
fileObj = new(xtra "FileIO")

-- open the file
openFile(fileObj,filename,1)

-- check to see if file opened ok
if status(fileObj) <> 0 then
err = error(fileObj,status(fileObj))
alert "Error:"&&err
return ""
end if

-- read the file
text = readFile(fileObj)

-- close the file
closeFile(fileObj)

--return the text
return text

end


Sample usage is illustrated below:

oUtilClass = new(script "UtilClass")

--Read html from the template
html = oUtilClass.readFromFile(the moviepath & "\\Templates\\summary report.htm")

--Fill in data..
global strSelectedDate
html = oUtilClass.findAndReplace(html, "$1", someVar)
html = oUtilClass.findAndReplace(html, "$2", anotherVar)

filename = the moviepath & "print.html"
oUtilClass.saveText(html, filename)

--Invoke through a browser..
fileXtra4Obj = xtra("FileXtra4").new()
fileXtra4Obj.fx_FileRunApp(the moviepath & "run.bat")



In run.bat, you just have to call print.html by writing "print.html", Duh!
Therefore, run.bat opens print.html with the default browser, which can then be printed, previewed by the courtesy of browser. Whats more, you also get to fiddle with niche layout settings at runtime. In other operating systems like linux, you just have to replace run.bat with a shell script.

Some Minor Tidbits

What if you wanted to generate a table at runtime? Here's what I'd do:

Generate HTML template from dreamweaver or MS word with one row of data in the table..
For example...
<html>
Some blah blah..

Name: $1 </br>
Age : $2 </br>

<table>
<tr>
<td> Subject </td>
<td> Marks </td>
</tr>

<tr>
<td> Some subject </td>
<td> 85 </td>
</tr>
</table>

</html>

Now, create a file template1_rows.txt containing the row data..<html>
<tr>
<td> $1 </td>
<td> $2 </td>
</tr>
Here's the big idea. Whenever you build a table, read in the row data template, fill it and append it to the main html. Here's an example. Highlighted code achieves dynamic table generation behavior.
 --Read html from the template
html = oUtilClass.readFromFile(the moviepath & "\\Templates\\template1.htm")

--Fill in data..
global strSelectedDate
html = oUtilClass.findAndReplace(html, "$1", name)
html = oUtilClass.findAndReplace(html, "$2", age)

tableRows = ""
--Read in the row template..
rowTemplate = oUtilClass.readFromFile(the moviepath & "\\Templates\\template1_rows.htm")

--Generate table rows..
repeat with row=1 to numRows
tableRow = rowTemplate
tableRow = oUtilClass.findAndReplace(tableRow , "$1", subject)

--Append data to tableRows..
tableRows = tableRows & rowTemplate
end repeat

--Fill in table data..
html = oUtilClass.findAndReplace(html, "$3", tableRows)

filename = the moviepath & "print.html"
oUtilClass.saveText(html, filename)

fileXtra4Obj = xtra("FileXtra4").new()
fileXtra4Obj.fx_FileRunApp(the moviepath & "run.bat")
I know, it looks complicated. But atleast this is transparent and you exactly know whats going on. Moreover, this approach gives you unlimited formatting options, works and is free. Once you get a hand of it, it'll seem pretty simple.

Controlling print behavior

If you don't want your table to break across pages, you can use . Beware, this only works with opera browser. So be sure to ship your software with opera. Even better, use opera portable (requires no installation), make appropriate changes to run.bat to invoke html with the shipped browser.

Comments and suggestions are welcome. If anyone has simpler and free approach, please let me know by posting comments.

Tuesday, June 1, 2010

Segmentation fault with c++ vector

Ever been in a situation where you got a seg. fault when you tried to push_back a pointer into the vector? What's more, you have a useless log file with no clues whatsoever. I had the same issue when i was working on an assignment with deadline in 2 hours. After whacking my head for 1-2 hours, I finally found a way to resolve the issue.

I was working on "simple ecosystem" project. The code where new fishes are created and added to the ecosystem seg. faulted. Take a look, I cut down unnecessary things to keep this example simple.
for (vector::iterator it = vecPossiblePositions.begin(); it!=vecPossiblePositions.end(); ++it)
{
//create a new fish..
Fish *f = new Fish();
f->setPosition(it->getX(), it->getY());

//This method does a push_back
//operation on some vector
ecosystem->addEcosystemObject(f);
}
If i comment out ecosystem->addEcosystemObject(f) line, then it runs without seg. fault. Apparently, the line Fish *f = new Fish() was causing the problem. So here's what i did.
Fish *f = NULL;
for (vector::iterator it = vecPossiblePositions.begin(); it!=vecPossiblePositions.end(); ++it)
{
//create a new fish..
f = new Fish();
f->setPosition(it->getX(), it->getY());

//This method does a push_back
//operation on some vector
ecosystem->addEcosystemObject(f);
}
and that fixed the problem! I have no idea why it worked. So, today's lesson of the day is "Keep the damn ptr declarations outside loops"

Enter teeki chawal

Got bored of same old food? Try this recipe..I found out about it from a friend of mine and made a few modifications of my own.

Here's what you need:
  1. Cooked rice
  2. Oil (obviously)
  3. Mirchi powder, jeera, salt, chopped onions, semi boiled and cut potato (one will do)
  4. Crushed tomatoes, c, carrots, beans, green peas, corn
Here's how you proceed:
  1. Heat a pan with lots of oil..
  2. Put jeera (one handful, needs to be more)
  3. Put onions and fry em' all at med flame
  4. Once onions are semi fried, put capsicum, potatoes and cook for like 7 mins
  5. Put remaining veggies and cook for another 7 mins.
  6. Add mirchi powder, and any other spices you fancy (Dhaniya powder, Hing, Garam masala will also do)
  7. Let it cook for another 5 mins..(At any point, if you notice that the veggies are burning, add a little bit of crushed tomato puree)
  8. Add 40% of the crushed tomatoes from the can.
  9. Cook for 10 mins.
  10. Now, taste the mixture, it should be slightly spicier, if not, add more spices. Also, at this point you should notice oil separating from the mixture
  11. Add cooked rice (cold one preferably), and stir for 3-5 mins..
That's it..enjoy your meal :)